pax_global_header00006660000000000000000000000064144202601310014503gustar00rootroot0000000000000052 comment=fb4486d5ab5d0cd3b6a71659c7d5eb4509f2a4ce HM-HM-18.0/000077500000000000000000000000001442026013100122415ustar00rootroot00000000000000HM-HM-18.0/.cproject000066400000000000000000000466711442026013100140710ustar00rootroot00000000000000 HM-HM-18.0/.gitattributes000066400000000000000000000003511442026013100151330ustar00rootroot00000000000000# Set the default behavior, in case people don't have core.autocrlf set. * text=auto # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. *.c text *.cpp text *.h text HM-HM-18.0/.gitignore000066400000000000000000000001301442026013100142230ustar00rootroot00000000000000dec.yuv rec.yuv str.bin /build/ /bin/ /lib/ core deploy *.sdf *.suo *.pyc .vs/ .vscode/ HM-HM-18.0/.gitlab-ci.yml000066400000000000000000000012341442026013100146750ustar00rootroot00000000000000stages: - build .build_template: stage: build script: - make realclean - make all only: refs: - master - merge_requests variables: - $CI_PROJECT_URL == 'https://vcgit.hhi.fraunhofer.de/jvet/HM' - $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'master' build_macos: extends: .build_template tags: - macos build_ubuntu2204: extends: .build_template tags: - ubuntu2204 build_ubuntu2004: extends: .build_template tags: - ubuntu2004 build_vc191x: extends: .build_template tags: - vc191x build_vc192x: extends: .build_template tags: - vc192x HM-HM-18.0/.project000066400000000000000000000046101442026013100137110ustar00rootroot00000000000000 HM org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, ?name? org.eclipse.cdt.make.core.append_environment true org.eclipse.cdt.make.core.autoBuildTarget all org.eclipse.cdt.make.core.buildArguments org.eclipse.cdt.make.core.buildCommand make org.eclipse.cdt.make.core.buildLocation ${workspace_loc:}/${ProjName}/build/linux org.eclipse.cdt.make.core.cleanBuildTarget clean org.eclipse.cdt.make.core.contents org.eclipse.cdt.make.core.activeConfigSettings org.eclipse.cdt.make.core.enableAutoBuild false org.eclipse.cdt.make.core.enableCleanBuild true org.eclipse.cdt.make.core.enableFullBuild true org.eclipse.cdt.make.core.fullBuildTarget all org.eclipse.cdt.make.core.stopOnError true org.eclipse.cdt.make.core.useDefaultBuildCmd true org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder org.eclipse.cdt.core.cnature org.eclipse.cdt.core.ccnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature HM-HM-18.0/.settings/000077500000000000000000000000001442026013100141575ustar00rootroot00000000000000HM-HM-18.0/.settings/org.eclipse.cdt.core.prefs000066400000000000000000000307011442026013100211330ustar00rootroot00000000000000#Fri Nov 12 15:27:20 CET 2010 eclipse.preferences.version=1 org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80 org.eclipse.cdt.core.formatter.alignment_for_compact_if=0 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16 org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48 org.eclipse.cdt.core.formatter.alignment_for_expression_list=0 org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.cdt.core.formatter.brace_position_for_block=next_line org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=next_line org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line org.eclipse.cdt.core.formatter.brace_position_for_switch=next_line org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line org.eclipse.cdt.core.formatter.compact_else_if=false org.eclipse.cdt.core.formatter.continuation_indentation=2 org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false org.eclipse.cdt.core.formatter.indent_empty_lines=false org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.cdt.core.formatter.indentation.size=2 org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=insert org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=true org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.cdt.core.formatter.lineSplit=100 org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.cdt.core.formatter.tabulation.char=space org.eclipse.cdt.core.formatter.tabulation.size=2 org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false HM-HM-18.0/.settings/org.eclipse.cdt.ui.prefs000066400000000000000000000001631442026013100206170ustar00rootroot00000000000000#Fri Nov 12 14:22:53 CET 2010 eclipse.preferences.version=1 formatter_profile=_TM formatter_settings_version=1 HM-HM-18.0/CMakeLists.txt000066400000000000000000000113731442026013100150060ustar00rootroot00000000000000# minimum required cmake version cmake_minimum_required( VERSION 3.5 FATAL_ERROR ) # project name if( EXTENSION_360_VIDEO ) project( HM360 ) else() project( HM ) endif() # use ccache find_program( CCACHE_FOUND ccache ) if( CCACHE_FOUND ) message( STATUS "ccache found. using it." ) set_property( GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache ) set_property( GLOBAL PROPERTY RULE_LAUNCH_LINK ccache ) endif() # set default CMAKE_BUILD_TYPE to Release if not set if( NOT CMAKE_BUILD_TYPE ) set( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE ) endif() if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) set( USE_ADDRESS_SANITIZER OFF CACHE BOOL "Compiles with -sanitize=address and links to libasan" ) endif() endif() set( EXTENSION_360_VIDEO OFF CACHE BOOL "If EXTENSION_360_VIDEO is on, 360Lib will be added" ) set( SET_ENABLE_TRACING OFF CACHE BOOL "Set ENABLE_TRACING as a compiler flag" ) set( ENABLE_TRACING OFF CACHE BOOL "If SET_ENABLE_TRACING is on, it will be set to this value" ) set( HIGH_BITDEPTH OFF CACHE BOOL "Build libraries and applications with high bit depth support" ) if( CMAKE_COMPILER_IS_GNUCC ) set( BUILD_STATIC OFF CACHE BOOL "Build static executables" ) endif() # set c++11 set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) # compile everything position independent (even static libraries) set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) # set verbose compile options #set( CMAKE_VERBOSE_MAKEFILE ON ) # use folders in IDEs for projects (e.g. lib sample app test) set_property( GLOBAL PROPERTY USE_FOLDERS ON ) # Include a utility module providing functions, macros, and settings include( ${CMAKE_SOURCE_DIR}/cmake/CMakeBuild/cmake/modules/BBuildEnv.cmake ) # Enable multithreading bb_multithreading() find_package(OpenMP) if( OpenMP_FOUND ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" ) set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}" ) endif() # Enable warnings for some generators and toolsets. # bb_enable_warnings( gcc warnings-as-errors -Wno-sign-compare ) # bb_enable_warnings( gcc -Wno-unused-variable ) # bb_enable_warnings( gcc-4.8 warnings-as-errors -Wno-unused-variable ) # for gcc 8.2: bb_enable_warnings( gcc warnings-as-errors -Wno-sign-compare -Wno-class-memaccess) if( XCODE ) bb_enable_warnings( clang warnings-as-errors -Wno-deprecated-declarations -Wno-unknown-attributes -Wno-deprecated-register -Wno-pessimizing-move -Wno-absolute-value -Wno-unused-const-variable ) else() bb_enable_warnings( clang warnings-as-errors -Wno-unknown-attributes -Wno-deprecated-register -Wno-pessimizing-move -Wno-absolute-value -Wno-unused-const-variable ) endif() #bb_enable_warnings( clang warnings-as-errors ) # enable warnings bb_enable_warnings( msvc warnings-as-errors "/wd4996" ) # enable sse4.1 build for all source files for gcc and clang if( UNIX OR MINGW ) add_compile_options( "-msse4.1" ) endif() # enable parallel build for Visual Studio if( MSVC ) add_compile_options( "/MP" ) add_compile_options( "/EHsc" ) endif() # set address sanitizer compiler arguments if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( USE_ADDRESS_SANITIZER ) # add compile options add_compile_options( "-fsanitize=address" ) add_link_options( "-fsanitize=address" ) endif() endif() if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0 ) add_compile_options( "-fabi-version=6" ) endif() endif() # add needed subdirectories add_subdirectory( "source/Lib/TLibCommon" ) add_subdirectory( "source/Lib/TLibCommonAnalyser" ) if( EXTENSION_360_VIDEO ) add_subdirectory( "source/Lib/Lib360" ) add_subdirectory( "source/Lib/AppEncHelper360" ) endif() add_subdirectory( "source/Lib/TLibDecoder" ) add_subdirectory( "source/Lib/TLibDecoderAnalyser" ) add_subdirectory( "source/Lib/TLibEncoder" ) add_subdirectory( "source/Lib/Utilities" ) add_subdirectory( "source/App/TAppDecoder" ) add_subdirectory( "source/App/TAppDecoderAnalyser" ) add_subdirectory( "source/App/TAppEncoder" ) add_subdirectory( "source/App/TAppMCTSExtractor" ) add_subdirectory( "source/App/Parcat" ) add_subdirectory( "source/App/SEIRemovalApp" ) add_subdirectory( "source/App/SEIFilmGrainApp" ) if( EXTENSION_360_VIDEO ) add_subdirectory( "source/App/utils/360ConvertApp" ) endif() HM-HM-18.0/COPYING000066400000000000000000000033201442026013100132720ustar00rootroot00000000000000The copyright in this software is being made available under the BSD License, included below. This software may be subject to other third party and contributor rights, including patent rights, and no such rights are granted under this license.   Copyright (c) 2010-2022, ITU/ISO/IEC All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ITU/ISO/IEC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. HM-HM-18.0/Makefile000066400000000000000000000126601442026013100137060ustar00rootroot00000000000000BUILD_SCRIPT := $(CURDIR)/cmake/CMakeBuild/bin/cmake.py # Define here a list of generic targets to be built separately using a suffix to select the variant and link option. # Examples: must be replaced by a make target defined below. # # How to build a single target: # make -a => build variant=debug,release,relwithdebinfo # make -r => build variant=release # make -d => build variant=debug # make -p => build variant=relwithdebinfo # # How to clean and build a single target: # make -ca => clean + build variant=debug,release,relwithdebinfo # make -cr => clean + build variant=release # make -cd => clean + build variant=debug # make -cp => clean + build variant=relwithdebinfo # TARGETS := TLibCommon TAppDecoder TAppDecoderAnalyser TLibDecoder TARGETS += TAppEncoder TLibEncoder Utilities MCTSExtractor SEIFilmGrainApp ifeq ($(OS),Windows_NT) ifneq ($(MSYSTEM),) # MSYS runtime environment UNAME_S := $(shell uname -s) PYTHON_LAUNCHER := python3 BUILD_CMD := $(PYTHON_LAUNCHER) $(BUILD_SCRIPT) else UNAME_S := Windows PY := $(wildcard c:/windows/py.*) ifeq ($(PY),) PYTHON_LAUNCHER := python else PYTHON_LAUNCHER := $(notdir $(PY)) endif # If a plain cmake.py is used, the exit codes won't arrive in make; i.e. build failures are reported as success by make. BUILD_CMD := $(PYTHON_LAUNCHER) $(BUILD_SCRIPT) ifeq ($(toolset),gcc) g := mgwmake endif endif else UNAME_S := $(shell uname -s) BUILD_CMD := $(BUILD_SCRIPT) ifeq ($(UNAME_S),Linux) # for Jenkins: run trace build only on Linux LINUXBUILD := TRUE endif ifeq ($(UNAME_S),Darwin) # MAC endif endif ifeq ($(j),) BUILD_JOBS += -j else BUILD_JOBS += -j$(j) endif ifneq ($(g),) CONFIG_OPTIONS += -g $(g) endif ifneq ($(toolset),) # aarch64 and mingw are two shortcuts to simplify toolset specification. ifeq ($(toolset),mingw) CONFIG_OPTIONS += toolset=x86_64-w64-mingw32-gcc-posix else CONFIG_OPTIONS += toolset=$(toolset) endif endif ifneq ($(address-model),) CONFIG_OPTIONS += address-model=$(address-model) endif ifneq ($(address-sanitizer),) CMAKE_OPTIONS += -DUSE_ADDRESS_SANITIZER=ON endif ifneq ($(high-bitdepth),) CMAKE_OPTIONS += -DHIGH_BITDEPTH=ON endif ifneq ($(verbose),) CMAKE_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE=ON endif ifneq ($(enable-tracing),) CONFIG_OPTIONS += -DSET_ENABLE_TRACING=ON -DENABLE_TRACING=$(enable-tracing) endif ifneq ($(static),) CONFIG_OPTIONS += -DBUILD_STATIC=$(static) endif BUILD_OPTIONS := $(CONFIG_OPTIONS) -b debug: $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug all: $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo release: $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=release relwithdebinfo: $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=relwithdebinfo clean: # clean is equal to realclean to ensure that CMake options are reset $(RM) -rf bin build lib # $(BUILD_CMD) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo --target clean clean-r: $(BUILD_CMD) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=release --target clean clean-d: $(BUILD_CMD) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug --target clean clean-p: $(BUILD_CMD) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=relwithdebinfo --target clean configure: $(BUILD_CMD) $(CONFIG_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo linuxbuild: ifeq ($(LINUXBUILD),TRUE) # option for automated jenkins build $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug endif # # project specific targets # # build the list of release, debug targets given the generic targets TARGETS_ALL := $(foreach t,$(TARGETS),$(t)-a) TARGETS_RELEASE := $(foreach t,$(TARGETS),$(t)-r) TARGETS_DEBUG := $(foreach t,$(TARGETS),$(t)-d) TARGETS_RELWITHDEBINFO := $(foreach t,$(TARGETS),$(t)-p) TARGETS_ALL_CLEAN_FIRST := $(foreach t,$(TARGETS),$(t)-ca) TARGETS_RELEASE_CLEAN_FIRST := $(foreach t,$(TARGETS),$(t)-cr) TARGETS_DEBUG_CLEAN_FIRST := $(foreach t,$(TARGETS),$(t)-cd) TARGETS_RELWITHDEBINFO_CLEAN_FIRST := $(foreach t,$(TARGETS),$(t)-cp) $(TARGETS_ALL): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo --target $(patsubst %-a,%,$@) $(TARGETS_ALL_CLEAN_FIRST): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug,release,relwithdebinfo --clean-first --target $(patsubst %-ca,%,$@) $(TARGETS_RELEASE): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=release --target $(patsubst %-r,%,$@) $(TARGETS_RELEASE_CLEAN_FIRST): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=release --clean-first --target $(patsubst %-cr,%,$@) $(TARGETS_DEBUG): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug --target $(patsubst %-d,%,$@) $(TARGETS_DEBUG_CLEAN_FIRST): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=debug --target $(patsubst %-cd,%,$@) --clean-first $(TARGETS_RELWITHDEBINFO): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=relwithdebinfo --target $(patsubst %-p,%,$@) $(TARGETS_RELWITHDEBINFO_CLEAN_FIRST): $(BUILD_CMD) $(BUILD_JOBS) $(BUILD_OPTIONS) $(CMAKE_OPTIONS) variant=relwithdebinfo --target $(patsubst %-cp,%,$@) --clean-first realclean: $(RM) -rf bin build lib .NOTPARALLEL: HM-HM-18.0/README.md000066400000000000000000000116371442026013100135300ustar00rootroot00000000000000HM reference software for HEVC ============================== This software package is the reference software for Rec. ITU-T H.265 | ISO/IEC 23008-2 High Efficiency Video Coding (HEVC). The reference software includes both encoder and decoder functionality. Reference software is useful in aiding users of a video coding standard to establish and test conformance and interoperability, and to educate users and demonstrate the capabilities of the standard. For these purposes, this software is provided as an aid for the study and implementation of Rec. ITU-T H.265 | ISO/IEC 23008-2 High Efficiency Video Coding. The software has been jointly developed by the ITU-T Video Coding Experts Group (VCEG, Question 6 of ITU-T Study Group 16) and the ISO/IEC Moving Picture Experts Group (MPEG, Working Group 11 of Subcommittee 29 of ISO/IEC Joint Technical Committee 1). The software is maintained by the Joint Video Experts Team (JVET) which is a joint collaboration of ITU-T Video Coding Experts Group (VCEG, Question 6 of ITU-T Study Group 16) and the ISO/IEC Moving Picture Experts Group (MPEG, Working Group 5 of Subcommittee 29 of ISO/IEC Joint Technical Committee 1). A software manual, which contains usage instructions, can be found in the "doc" subdirectory of this software package. Build instructions ================== The CMake tool is used to create platform-specific build files. Although CMake may be able to generate 32-bit binaries, **it is generally suggested to build 64-bit binaries**. 32-bit binaries are not able to access more than 2GB of RAM, which will not be sufficient for coding larger image formats. Building in 32-bit environments is not tested and will not be supported. Build instructions for plain CMake (suggested) ---------------------------------------------- **Note:** A working CMake installation is required for building the software. CMake generates configuration files for the compiler environment/development environment on each platform. The following is a list of examples for Windows (MS Visual Studio), macOS (Xcode) and Linux (make). Open a command prompt on your system and change into the root directory of this project. Create a build directory in the root directory: ```bash mkdir build ``` Use one of the following CMake commands, based on your platform. Feel free to change the commands to satisfy your needs. **Windows Visual Studio 2015/17/19 64 Bit:** Use the proper generator string for generating Visual Studio files, e.g. for VS 2015: ```bash cd build cmake .. -G "Visual Studio 14 2015 Win64" ``` Then open the generated solution file in MS Visual Studio. For VS 2017 use "Visual Studio 15 2017 Win64", for VS 2019 use "Visual Studio 16 2019". Visual Studio 2019 also allows you to open the CMake directory directly. Choose "File->Open->CMake" for this option. **macOS Xcode:** For generating an Xcode workspace type: ```bash cd build cmake .. -G "Xcode" ``` Then open the generated work space in Xcode. For generating Makefiles with optional non-default compilers, use the following commands: ```bash cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc-9 -DCMAKE_CXX_COMPILER=g++-9 ``` In this example the brew installed GCC 9 is used for a release build. **Linux** For generating Linux Release Makefile: ```bash cd build cmake .. -DCMAKE_BUILD_TYPE=Release ``` For generating Linux Debug Makefile: ```bash cd build cmake .. -DCMAKE_BUILD_TYPE=Debug ``` Then type ```bash make -j ``` For more details, refer to the CMake documentation: https://cmake.org/cmake/help/latest/ Build instructions for make --------------------------- **Note:** The build instructions in this section require the make tool and Python to be installed, which are part of usual Linux and macOS environments. See below for installation instruction for Python and GnuWin32 on Windows. Open a command prompt on your system and change into the root directory of this project. To use the default system compiler simply call: ```bash make all ``` **MSYS2 and MinGW (Windows)** **Note:** Build files for MSYS MinGW were added on request. The build platform is not regularily tested and can't be supported. Open an MSYS MinGW 64-Bit terminal and change into the root directory of this project. Call: ```bash make all toolset=gcc ``` The following tools need to be installed for MSYS2 and MinGW: Download CMake: http://www.cmake.org/ and install it. Python and GnuWin32 are not mandatory, but they simplify the build process for the user. python: https://www.python.org/downloads/release/python-371/ gnuwin32: https://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/0.6.30/GetGnuWin32-0.6.3.exe/download To use MinGW, install MSYS2: http://repo.msys2.org/distrib/msys2-x86_64-latest.exe Installation instructions: https://www.msys2.org/ Install the needed toolchains: ```bash pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain git subversion mingw-w64-i686-cmake mingw-w64-x86_64-cmake ``` HM-HM-18.0/cfg/000077500000000000000000000000001442026013100130005ustar00rootroot00000000000000HM-HM-18.0/cfg/encoder_intra_high_throughput_rext.cfg000066400000000000000000000216761442026013100226430ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : high-throughput-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" IntraConstraintFlag : 1 # Intra constraint flag - must be 1 in high-throughput-RExt profile #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) AlignCABACBeforeBypass : 1 # Align the CABAC engine to a defined fraction of a bit prior to coding bypass data. ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main.cfg000066400000000000000000000154621442026013100173110ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main10.cfg000066400000000000000000000154641442026013100174540ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main10_ctc_subsample.cfg000066400000000000000000000156351442026013100223600ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP TemporalSubsampleRatio : 8 # only encode every eighth frame (for CTC runtime reduction) #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main_ctc_subsample.cfg000066400000000000000000000156331442026013100222150ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP TemporalSubsampleRatio : 8 # only encode every eighth frame (for CTC runtime reduction) #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main_rext.cfg000066400000000000000000000212661442026013100203520ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_intra_main_rext_subsample.cfg000066400000000000000000000214371442026013100224250ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 1 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP TemporalSubsampleRatio : 8 # only encode every eighth frame (for CTC runtime reduction) #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_lowdelay_P_main.cfg000066400000000000000000000253711442026013100202730ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: P 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -9 -17 -25 0 Frame2: P 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -10 -18 1 -1 5 1 1 1 0 1 Frame3: P 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -11 -19 1 -1 5 0 1 1 1 1 Frame4: P 4 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -4 -12 -20 1 -1 5 0 1 1 1 1 Frame5: P 5 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -13 -21 1 -1 5 0 1 1 1 1 Frame6: P 6 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -6 -14 -22 1 -1 5 0 1 1 1 1 Frame7: P 7 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -7 -15 -23 1 -1 5 0 1 1 1 1 Frame8: P 8 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -8 -16 -24 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 0 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.10 # Enable filter at every 8th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_lowdelay_P_main10.cfg000066400000000000000000000253731442026013100204360ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: P 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -9 -17 -25 0 Frame2: P 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -10 -18 1 -1 5 1 1 1 0 1 Frame3: P 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -11 -19 1 -1 5 0 1 1 1 1 Frame4: P 4 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -4 -12 -20 1 -1 5 0 1 1 1 1 Frame5: P 5 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -13 -21 1 -1 5 0 1 1 1 1 Frame6: P 6 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -6 -14 -22 1 -1 5 0 1 1 1 1 Frame7: P 7 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -7 -15 -23 1 -1 5 0 1 1 1 1 Frame8: P 8 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -8 -16 -24 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 0 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.10 # Enable filter at every 8th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_lowdelay_main.cfg000066400000000000000000000253721442026013100200150ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -9 -17 -25 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -10 -18 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -11 -19 1 -1 5 0 1 1 1 1 Frame4: B 4 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -4 -12 -20 1 -1 5 0 1 1 1 1 Frame5: B 5 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -13 -21 1 -1 5 0 1 1 1 1 Frame6: B 6 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -6 -14 -22 1 -1 5 0 1 1 1 1 Frame7: B 7 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -7 -15 -23 1 -1 5 0 1 1 1 1 Frame8: B 8 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -8 -16 -24 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 0 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.10 # Enable filter at every 8th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_lowdelay_main10.cfg000066400000000000000000000253761442026013100201620ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -9 -17 -25 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -10 -18 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -11 -19 1 -1 5 0 1 1 1 1 Frame4: B 4 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -4 -12 -20 1 -1 5 0 1 1 1 1 Frame5: B 5 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -13 -21 1 -1 5 0 1 1 1 1 Frame6: B 6 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -6 -14 -22 1 -1 5 0 1 1 1 1 Frame7: B 7 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -7 -15 -23 1 -1 5 0 1 1 1 1 Frame8: B 8 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -8 -16 -24 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 0 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.10 # Enable filter at every 8th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_lowdelay_main_rext.cfg000066400000000000000000000311761442026013100210560ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -9 -17 -25 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -10 -18 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -11 -19 1 -1 5 0 1 1 1 1 Frame4: B 4 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -4 -12 -20 1 -1 5 0 1 1 1 1 Frame5: B 5 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -13 -21 1 -1 5 0 1 1 1 1 Frame6: B 6 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -6 -14 -22 1 -1 5 0 1 1 1 1 Frame7: B 7 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -7 -15 -23 1 -1 5 0 1 1 1 1 Frame8: B 8 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -8 -16 -24 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 0 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.10 # Enable filter at every 8th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_randomaccess_main.cfg000066400000000000000000000313711442026013100206330ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 2 -16 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -24 8 1 8 3 1 1 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -20 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -18 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -7 1 9 1 -2 6 0 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 5 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -11 1 5 1 -2 6 0 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 3 -2 -14 2 1 -3 5 0 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -13 1 3 1 1 4 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -3 -15 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 4 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnableFlag : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_randomaccess_main10.cfg000066400000000000000000000313731442026013100207760ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 2 -16 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -24 8 1 8 3 1 1 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -20 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -18 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -7 1 9 1 -2 6 0 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 5 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -11 1 5 1 -2 6 0 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 3 -2 -14 2 1 -3 5 0 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -13 1 3 1 1 4 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -3 -15 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 4 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnableFlag : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/encoder_randomaccess_main_rext.cfg000066400000000000000000000352631442026013100217010ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 2 -16 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -24 8 1 8 3 1 1 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -20 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -18 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -7 1 9 1 -2 6 0 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 5 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -11 1 5 1 -2 6 0 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 3 -2 -14 2 1 -3 5 0 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -13 1 3 1 1 4 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 4 -1 -3 -15 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 1 # Enable/disable GOP Based Temporal Filter TemporalFilterPastRefs : 4 # Number of past references for temporal prefilter TemporalFilterFutureRefs : 4 # Number of future references for temporal prefilter TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/hbd/000077500000000000000000000000001442026013100135355ustar00rootroot00000000000000HM-HM-18.0/cfg/hbd/12-bit.cfg000066400000000000000000000000251442026013100152110ustar00rootroot00000000000000InternalBitDepth: 12HM-HM-18.0/cfg/hbd/16-bit.cfg000066400000000000000000000000251442026013100152150ustar00rootroot00000000000000InternalBitDepth: 16HM-HM-18.0/cfg/hbd/hbd.cfg000066400000000000000000000000501442026013100147460ustar00rootroot00000000000000TemporalFilter: 0 ExtendedPrecision: 1HM-HM-18.0/cfg/lossless/000077500000000000000000000000001442026013100146475ustar00rootroot00000000000000HM-HM-18.0/cfg/lossless/lossless.cfg000066400000000000000000000002531442026013100171770ustar00rootroot00000000000000CostMode : lossless ExtendedPrecision : 1 TransquantBypassEnableFlag : 1 CUTransquantBypassFlagForce : 1 IntraReferenceSmoothing : 0HM-HM-18.0/cfg/misc/000077500000000000000000000000001442026013100137335ustar00rootroot00000000000000HM-HM-18.0/cfg/misc/encoder_lowdelay_P_main10_GOP4.cfg000066400000000000000000000234211442026013100221520ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 4 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: P 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -9 -13 0 Frame2: P 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -6 -10 1 -1 5 1 1 1 0 1 Frame3: P 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -7 -11 1 -1 5 0 1 1 1 1 Frame4: P 4 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -4 -8 -12 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 0 # Enable/disable reading future frames TemporalFilterStrengthFrame4 : 0.40 # Enable filter at every 4th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_lowdelay_P_main_GOP4.cfg000066400000000000000000000234171442026013100220160ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 4 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: P 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -9 -13 0 Frame2: P 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -6 -10 1 -1 5 1 1 1 0 1 Frame3: P 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -7 -11 1 -1 5 0 1 1 1 1 Frame4: P 4 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -4 -8 -12 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 0 # Enable/disable reading future frames TemporalFilterStrengthFrame4 : 0.40 # Enable filter at every 4th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_lowdelay_main10_GOP4.cfg000066400000000000000000000234231442026013100216750ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 4 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -9 -13 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -6 -10 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -7 -11 1 -1 5 0 1 1 1 1 Frame4: B 4 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -4 -8 -12 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 0 # Enable/disable reading future frames TemporalFilterStrengthFrame4 : 0.40 # Enable filter at every 4th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_lowdelay_main_GOP4.cfg000066400000000000000000000234211442026013100215320ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 4 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -9 -13 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -6 -10 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -7 -11 1 -1 5 0 1 1 1 1 Frame4: B 4 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -4 -8 -12 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 0 # Enable/disable reading future frames TemporalFilterStrengthFrame4 : 0.40 # Enable filter at every 4th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_lowdelay_main_field_coding.cfg000066400000000000000000000252451442026013100234350ustar00rootroot00000000000000#======== File I/O ===================== FieldCoding : 1 # (0: Frame based coding, 1: Field based coding) TopFieldFirst : 1 # Field parity order (1: Top field first, 0: Bottom field first) ConformanceMode : 1 BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile/Level ================ Profile : main Level : 6.2 #======== SEI =========================== VuiParametersPresent : 1 SEIActiveParameterSets : 1 SEIPictureTiming : 1 FrameFieldInfoPresentFlag : 1 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 2 3 0.0 0.0 0 0 0.4624 0 0 0 8 8 -1 -2 -9 -10 -17 -18 -25 -26 0 Frame2: B 3 4 0.0 0.0 0 0 0.4624 0 0 0 8 9 -1 -2 -3 -10 -11 -18 -19 -26 -27 1 -1 9 1 1 1 1 1 1 1 1 1 Frame3: B 4 2 0.0 0.0 0 0 0.4624 0 0 0 8 8 -1 -2 -3 -4 -11 -12 -19 -20 1 -1 10 1 1 1 1 1 1 1 0 0 1 Frame4: B 5 3 0.0 0.0 0 0 0.4624 0 0 0 8 9 -1 -2 -3 -4 -5 -12 -13 -20 -21 1 -1 9 1 1 1 1 1 1 1 1 1 Frame5: B 6 3 0.0 0.0 0 0 0.4624 0 0 0 8 8 -1 -2 -5 -6 -13 -14 -21 -22 1 -1 10 1 0 0 1 1 1 1 1 1 1 Frame6: B 7 4 0.0 0.0 0 0 0.4624 0 0 0 8 9 -1 -2 -3 -6 -7 -14 -15 -22 -23 1 -1 9 1 1 1 1 1 1 1 1 1 Frame7: B 8 1 0.0 0.0 0 0 0.578 0 0 0 8 8 -1 -2 -7 -8 -15 -16 -23 -24 1 -1 10 1 0 0 1 1 1 1 1 1 1 Frame8: B 9 1 0.0 0.0 0 0 0.578 0 0 0 8 9 -1 -2 -3 -8 -9 -16 -17 -24 -25 1 -1 9 1 1 1 1 1 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_lowdelay_main_rext_GOP4.cfg000066400000000000000000000272251442026013100226020ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : -1 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 0 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 4 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -1 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 1 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -5 -9 -13 0 Frame2: B 2 4 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -2 -6 -10 1 -1 5 1 1 1 0 1 Frame3: B 3 5 -6.5 0.2590 0 0 1.0 0 0 0 4 4 -1 -3 -7 -11 1 -1 5 0 1 1 1 1 Frame4: B 4 1 0.0 0.0 0 0 1.0 0 0 0 4 4 -1 -4 -8 -12 1 -1 5 0 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 0 # Enable/disable reading future frames TemporalFilterStrengthFrame4 : 0.40 # Enable filter at every 4th frame with strength #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main10_GOP16.cfg000066400000000000000000000314251442026013100226030ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 3 -16 -24 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -16 8 1 8 4 1 1 0 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -12 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -10 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 1 9 1 -2 6 1 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 6 0 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -11 1 5 1 -2 6 1 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 -14 2 1 -3 6 0 1 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 -13 1 3 1 1 5 1 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 -15 1 1 -2 6 1 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 1 # Enable/disable reading future frames TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnableFlag : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main10_GOP8.cfg000066400000000000000000000240571442026013100225270ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main10 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 8 1 0.0 0.0 0 0 0.442 0 0 0 2 3 -8 -12 -16 0 Frame2: B 4 2 0.0 0.0 0 0 0.3536 0 0 1 2 3 -4 -8 4 1 4 4 1 1 0 1 Frame3: B 2 3 0.0 0.0 0 0 0.3536 0 0 2 2 4 -2 -6 2 6 1 2 4 1 1 1 1 Frame4: B 1 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 1 3 7 1 1 5 1 0 1 1 1 Frame5: B 3 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 1 5 1 -2 5 1 1 1 1 0 Frame6: B 6 3 0.0 0.0 0 0 0.3536 0 0 2 2 3 -2 -6 2 1 -3 5 0 1 1 1 0 Frame7: B 5 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -5 1 3 1 1 4 1 1 1 1 Frame8: B 7 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 -7 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_2tids.cfg000066400000000000000000000237121442026013100226730ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 8 1 0.0 0.0 0 0 0.442 0 0 0 4 4 -8 -10 -12 -16 0 Frame2: B 4 2 0.0 0.0 0 0 0.3536 0 0 0 2 3 -4 -6 4 1 4 5 1 1 0 0 1 Frame3: B 2 3 0.0 0.0 0 0 0.3536 0 0 0 2 4 -2 -4 2 6 1 2 4 1 1 1 1 Frame4: B 1 4 0.0 0.0 0 0 0.68 0 0 1 2 4 -1 1 3 7 1 1 5 1 0 1 1 1 Frame5: B 3 4 0.0 0.0 0 0 0.68 0 0 1 2 4 -1 -3 1 5 1 -2 5 1 1 1 1 0 Frame6: B 6 3 0.0 0.0 0 0 0.3536 0 0 0 2 4 -2 -4 -6 2 1 -3 5 1 1 1 1 0 Frame7: B 5 4 0.0 0.0 0 0 0.68 0 0 1 2 4 -1 -5 1 3 1 1 5 1 0 1 1 1 Frame8: B 7 4 0.0 0.0 0 0 0.68 0 0 1 2 4 -1 -3 -7 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1=constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_GOP16.cfg000066400000000000000000000314221442026013100224370ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 3 -16 -24 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -16 8 1 8 4 1 1 0 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -12 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -10 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 1 9 1 -2 6 1 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 6 0 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -11 1 5 1 -2 6 1 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 -14 2 1 -3 6 0 1 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 -13 1 3 1 1 5 1 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 -15 1 1 -2 6 1 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 1 # Enable/disable reading future frames TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnableFlag : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_GOP8.cfg000066400000000000000000000240551442026013100223640ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile ================ Profile : main #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 8 1 0.0 0.0 0 0 0.442 0 0 0 2 3 -8 -12 -16 0 Frame2: B 4 2 0.0 0.0 0 0 0.3536 0 0 1 2 3 -4 -8 4 1 4 4 1 1 0 1 Frame3: B 2 3 0.0 0.0 0 0 0.3536 0 0 2 2 4 -2 -6 2 6 1 2 4 1 1 1 1 Frame4: B 1 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 1 3 7 1 1 5 1 0 1 1 1 Frame5: B 3 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 1 5 1 -2 5 1 1 1 1 0 Frame6: B 6 3 0.0 0.0 0 0 0.3536 0 0 2 2 3 -2 -6 2 1 -3 5 0 1 1 1 0 Frame7: B 5 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -5 1 3 1 1 4 1 1 1 1 Frame8: B 7 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 -7 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_field_coding.cfg000077500000000000000000000305021442026013100242520ustar00rootroot00000000000000#======== File I/O ===================== FieldCoding : 1 # (0: Frame based coding, 1: Field based coding) TopFieldFirst : 1 # Field parity order (1: Top field first, 0: Bottom field first) ConformanceMode : 1 BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile/Level ================ Profile : main Level : 6.2 #======== SEI =========================== VuiParametersPresent : 1 SEIActiveParameterSets : 1 SEIPictureTiming : 1 FrameFieldInfoPresentFlag : 1 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) # field coding GOP: Exchanged coding order of 16th and 17th field for more efficient encoding # When EfficientFieldIRAPEnabled=1 is enabled, this has no additional effect # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 17 1 0.0 0.0 0 0 0.442 0 0 0 4 4 -16 -17 -20 -21 0 Frame2: B 16 1 0.0 0.0 0 0 0.442 0 0 0 3 3 -15 -16 1 1 1 5 1 1 0 0 1 Frame3: B 8 2 0.0 0.0 0 0 0.3536 0 0 0 2 4 -7 -8 8 9 1 8 4 1 1 1 1 Frame4: B 9 2 0.0 0.0 0 0 0.3536 0 0 0 2 5 -1 -8 -9 7 8 1 -1 5 1 1 1 1 1 Frame5: B 4 3 0.0 0.0 0 0 0.3536 0 0 0 2 6 -3 -4 4 5 12 13 1 5 6 1 1 1 1 1 1 Frame6: B 5 3 0.0 0.0 0 0 0.3536 0 0 0 2 7 -1 -4 -5 3 4 11 12 1 -1 7 1 1 1 1 1 1 1 Frame7: B 2 3 0.0 0.0 0 0 0.3536 0 0 0 2 8 -1 -2 2 3 6 7 14 15 1 3 8 1 1 1 1 1 1 1 1 Frame8: B 3 4 0.0 0.0 0 0 0.68 0 0 0 2 8 -1 -2 1 2 5 6 13 14 1 -1 9 1 0 1 1 1 1 1 1 1 Frame9: B 6 3 0.0 0.0 0 0 0.3536 0 0 0 2 6 -1 -2 2 3 10 11 1 -3 9 0 0 1 1 1 1 1 1 0 Frame10: B 7 4 0.0 0.0 0 0 0.68 0 0 0 2 7 -1 -2 -3 1 2 9 10 1 -1 7 1 1 1 1 1 1 1 Frame11: B 12 3 0.0 0.0 0 0 0.3536 0 0 0 2 4 -3 -4 4 5 1 -5 8 0 0 0 1 1 1 1 0 Frame12: B 13 3 0.0 0.0 0 0 0.3536 0 0 0 2 5 -1 -4 -5 3 4 1 -1 5 1 1 1 1 1 Frame13: B 10 3 0.0 0.0 0 0 0.3536 0 0 0 2 6 -1 -2 2 3 6 7 1 3 6 1 1 1 1 1 1 Frame14: B 11 4 0.0 0.0 0 0 0.68 0 0 0 2 7 -1 -2 -3 1 2 5 6 1 -1 7 1 1 1 1 1 1 1 Frame15: B 14 3 0.0 0.0 0 0 0.3536 0 0 0 2 5 -1 -2 -5 2 3 1 -3 8 0 1 0 1 1 1 1 0 Frame16: B 15 4 0.0 0.0 0 0 0.68 0 0 0 2 6 -1 -2 -3 -6 1 2 1 -1 6 1 1 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1=constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Constant lossless-value signaling per CU, if TransquantBypassEnableFlag is 1. #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_field_coding_simple_GOP.cfg000066400000000000000000000311731442026013100263320ustar00rootroot00000000000000#======== File I/O ===================== FieldCoding : 1 # (0: Frame based coding, 1: Field based coding) TopFieldFirst : 1 # Field parity order (1: Top field first, 0: Bottom field first) ConformanceMode : 1 BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile/Level ================ Profile : main Level : 6.2 #======== SEI =========================== VuiParametersPresent : 1 SEIActiveParameterSets : 1 SEIPictureTiming : 1 FrameFieldInfoPresentFlag : 1 #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) # simple field coding GOP: When EfficientFieldIRAPEnabled=1 is enabled, the order of frames 16 and 17 is exchanged # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 0.442 0 0 0 8 8 -15 -16 -19 -20 -23 -24 -31 -32 0 Frame2: B 17 1 0.0 0.0 0 0 0.442 0 0 0 4 9 -1 -16 -17 -20 -21 -24 -25 -32 -33 1 -1 9 1 1 1 1 1 1 1 1 1 Frame3: B 8 2 0.0 0.0 0 0 0.3536 0 0 0 4 6 -7 -8 -11 -12 8 9 1 9 10 1 1 1 1 1 0 0 0 0 1 Frame4: B 9 3 0.0 0.0 0 0 0.3536 0 0 0 4 7 -1 -8 -9 -12 -13 7 8 1 -1 7 1 1 1 1 1 1 1 Frame5: B 4 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -3 -4 -7 -8 4 5 12 13 1 5 8 1 1 1 1 1 1 1 1 Frame6: B 5 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -4 -5 -8 -9 3 4 11 12 1 -1 9 1 1 1 1 1 1 1 1 1 Frame7: B 2 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -1 -2 2 3 6 7 14 15 1 3 10 1 1 1 0 0 1 1 1 1 1 Frame8: B 3 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -2 -3 1 2 5 6 13 14 1 -1 9 1 1 1 1 1 1 1 1 1 Frame9: B 6 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -1 -2 -5 -6 2 3 10 11 1 -3 10 0 1 1 1 1 1 1 1 1 0 Frame10: B 7 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -2 -3 -6 -7 1 2 9 10 1 -1 9 1 1 1 1 1 1 1 1 1 Frame11: B 12 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -3 -4 -7 -8 -11 -12 4 5 1 -5 10 0 1 1 1 1 1 1 1 1 0 Frame12: B 13 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -4 -5 -8 -9 -12 -13 3 4 1 -1 9 1 1 1 1 1 1 1 1 1 Frame13: B 10 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -1 -2 -9 -10 2 3 6 7 1 3 10 1 1 1 0 0 1 1 1 1 1 Frame14: B 11 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -2 -3 -10 -11 1 2 5 6 1 -1 9 1 1 1 1 1 1 1 1 1 Frame15: B 14 3 0.0 0.0 0 0 0.3536 0 0 0 4 8 -1 -2 -5 -6 -13 -14 2 3 1 -3 10 0 1 1 1 1 1 1 1 1 0 Frame16: B 15 4 0.0 0.0 0 0 0.68 0 0 0 4 9 -1 -2 -3 -6 -7 -14 -15 1 2 1 -1 9 1 1 1 1 1 1 1 1 1 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1=constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream) #=========== Misc. ============ InternalBitDepth : 8 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Constant lossless-value signaling per CU, if TransquantBypassEnableFlag is 1. #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_rext_GOP16.cfg000066400000000000000000000353141442026013100235050ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 16 # GOP Size (number of B slice = GOPSize-1) ReWriteParamSetsFlag : 1 # Write parameter sets with every IRAP IntraQPOffset : -3 LambdaFromQpEnable : 1 # see JCTVC-X0038 for suitable parameters for IntraQPOffset, QPoffset, QPOffsetModelOff, QPOffsetModelScale when enabled # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 16 1 0.0 0.0 0 0 1.0 0 0 0 2 3 -16 -24 -32 0 Frame2: B 8 1 -4.8848 0.2061 0 0 1.0 0 0 1 2 3 -8 -16 8 1 8 4 1 1 0 1 Frame3: B 4 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 4 -4 -12 4 12 1 4 4 1 1 1 1 Frame4: B 2 5 -5.90 0.2333 0 0 1.0 0 0 3 2 5 -2 -10 2 6 14 1 2 5 1 1 1 1 1 Frame5: B 1 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 1 3 7 15 1 1 6 1 0 1 1 1 1 Frame6: B 3 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 1 5 13 1 -2 6 1 1 1 1 1 0 Frame7: B 6 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 2 10 1 -3 6 0 1 1 1 1 0 Frame8: B 5 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 1 3 11 1 1 5 1 1 1 1 1 Frame9: B 7 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 1 9 1 -2 6 1 1 1 1 1 0 Frame10: B 12 4 -5.7476 0.2286 0 0 1.0 0 0 2 2 3 -4 -12 4 1 -5 6 0 0 1 1 1 0 Frame11: B 10 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -10 2 6 1 2 4 1 1 1 1 Frame12: B 9 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -9 1 3 7 1 1 5 1 1 1 1 1 Frame13: B 11 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -11 1 5 1 -2 6 1 1 1 1 1 0 Frame14: B 14 5 -5.90 0.2333 0 0 1.0 0 0 3 2 4 -2 -6 -14 2 1 -3 6 0 1 1 1 1 0 Frame15: B 13 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -5 -13 1 3 1 1 5 1 1 1 1 1 Frame16: B 15 6 -7.1444 0.3 0 0 1.0 0 0 4 2 5 -1 -3 -7 -15 1 1 -2 6 1 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 384 # (0: Search range is a Full frame) ASR : 1 # Adaptive motion search range MinSearchWindow : 96 # Minimum motion search window size for the adaptive window ME BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #=========== TemporalFilter ================= TemporalFilter : 0 # Enable/disable GOP Based Temporal Filter TemporalFilterFutureReference : 1 # Enable/disable reading future frames TemporalFilterStrengthFrame8 : 0.95 # Enable filter at every 8th frame with given strength TemporalFilterStrengthFrame16 : 1.5 # Enable filter at every 16th frame with given strength, longer intervals has higher priority #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/encoder_randomaccess_main_rext_GOP8.cfg000066400000000000000000000277471442026013100234410ustar00rootroot00000000000000#======== File I/O ===================== BitstreamFile : str.bin ReconFile : rec.yuv #======== Profile definition ============== Profile : main-RExt # Profile name to use for encoding. Use main (for FDIS main), main10 (for FDIS main10), main-still-picture, main-RExt, high-throughput-RExt, main-SCC Tier : main # Tier to use for interpretation of --Level (main or high only)" #======== Unit definition ================ MaxCUWidth : 64 # Maximum coding unit width in pixel MaxCUHeight : 64 # Maximum coding unit height in pixel MaxPartitionDepth : 4 # Maximum coding unit depth QuadtreeTULog2MaxSize : 5 # Log2 of maximum transform size for # quadtree-based TU coding (2...6) QuadtreeTULog2MinSize : 2 # Log2 of minimum transform size for # quadtree-based TU coding (2...6) QuadtreeTUMaxDepthInter : 3 QuadtreeTUMaxDepthIntra : 3 #======== Coding Structure ============= IntraPeriod : 32 # Period of I-Frame ( -1 = only first) DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI GOPSize : 8 # GOP Size (number of B slice = GOPSize-1) # Type POC QPoffset QPOffsetModelOff QPOffsetModelScale CbQPoffset CrQPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures predict deltaRPS #ref_idcs reference idcs Frame1: B 8 1 0.0 0.0 0 0 0.442 0 0 0 2 3 -8 -12 -16 0 Frame2: B 4 2 0.0 0.0 0 0 0.3536 0 0 1 2 3 -4 -8 4 1 4 4 1 1 0 1 Frame3: B 2 3 0.0 0.0 0 0 0.3536 0 0 2 2 4 -2 -6 2 6 1 2 4 1 1 1 1 Frame4: B 1 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 1 3 7 1 1 5 1 0 1 1 1 Frame5: B 3 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 1 5 1 -2 5 1 1 1 1 0 Frame6: B 6 3 0.0 0.0 0 0 0.3536 0 0 2 2 3 -2 -6 2 1 -3 5 0 1 1 1 0 Frame7: B 5 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -5 1 3 1 1 4 1 1 1 1 Frame8: B 7 4 0.0 0.0 0 0 0.68 0 0 3 2 4 -1 -3 -7 1 1 -2 5 1 1 1 1 0 #=========== Motion Search ============= FastSearch : 1 # 0:Full search 1:TZ search SearchRange : 64 # (0: Search range is a Full frame) BipredSearchRange : 4 # Search range for bi-prediction refinement HadamardME : 1 # Use of hadamard measure for fractional ME FEN : 1 # Fast encoder decision FDM : 1 # Fast Decision for Merge RD cost #======== Quantization ============= QP : 32 # Quantization parameter(0-51) MaxDeltaQP : 0 # CU-based multi-QP optimization MaxCuDQPDepth : 0 # Max depth of a minimum CuDQP for sub-LCU-level delta QP DeltaQpRD : 0 # Slice-based multi-QP optimization RDOQ : 1 # RDOQ RDOQTS : 1 # RDOQ for transform skip SliceChromaQPOffsetPeriodicity: 0 # Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. SliceCbQpOffsetIntraOrPeriodic: 0 # Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. SliceCrQpOffsetIntraOrPeriodic: 0 # Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. #=========== Deblock Filter ============ LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param) LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter) LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6 LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6 DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0) #=========== Misc. ============ InternalBitDepth : 10 # codec operating bit-depth #=========== Coding Tools ================= SAO : 1 # Sample adaptive offset (0: OFF, 1: ON) AMP : 1 # Asymmetric motion partitions (0: OFF, 1: ON) TransformSkip : 1 # Transform skipping (0: OFF, 1: ON) TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON) SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON) #============ Slices ================ SliceMode : 0 # 0: Disable all slice options. # 1: Enforce maximum number of LCU in an slice, # 2: Enforce maximum number of bytes in an 'slice' # 3: Enforce maximum number of tiles in a slice SliceArgument : 1500 # Argument for 'SliceMode'. # If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice. # If SliceMode==2 it represents max. bytes per slice. # If SliceMode==3 it represents max. tiles per slice. LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary. # 0:not across, 1: across #============ PCM ================ PCMEnabledFlag : 0 # 0: No PCM mode PCMLog2MaxSize : 5 # Log2 of maximum PCM block size. PCMLog2MinSize : 3 # Log2 of minimum PCM block size. PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples. #============ Tiles ================ TileUniformSpacing : 0 # 0: the column boundaries are indicated by TileColumnWidth array, the row boundaries are indicated by TileRowHeight array # 1: the column and row boundaries are distributed uniformly NumTileColumnsMinus1 : 0 # Number of tile columns in a picture minus 1 TileColumnWidthArray : 2 3 # Array containing tile column width values in units of CTU (from left to right in picture) NumTileRowsMinus1 : 0 # Number of tile rows in a picture minus 1 TileRowHeightArray : 2 # Array containing tile row height values in units of CTU (from top to bottom in picture) LFCrossTileBoundaryFlag : 1 # In-loop filtering is across or not across tile boundary. # 0:not across, 1: across #============ WaveFront ================ WaveFrontSynchro : 0 # 0: No WaveFront synchronisation (WaveFrontSubstreams must be 1 in this case). # >0: WaveFront synchronises with the LCU above and to the right by this many LCUs. #=========== Quantization Matrix ================= ScalingList : 0 # ScalingList 0 : off, 1 : default, 2 : file read ScalingListFile : scaling_list.txt # Scaling List file name. If file is not exist, use Default Matrix. #============ Lossless ================ TransquantBypassEnable : 0 # Value of PPS flag. CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled #============ Rate Control ====================== RateControl : 0 # Rate control: enable rate control TargetBitrate : 1000000 # Rate control: target bitrate, in bps KeepHierarchicalBit : 2 # Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation LCULevelRateControl : 1 # Rate control: 1: LCU level RC; 0: picture level RC RCLCUSeparateModel : 1 # Rate control: use LCU level separate R-lambda model InitialQP : 0 # Rate control: initial QP RCForceIntraQP : 0 # Rate control: force intra QP to be equal to initial QP #=========== RExt ============ ExtendedPrecision : 0 # Increased internal accuracies to support high bit depths (not valid in V1 profiles) TransformSkipLog2MaxSize : 2 # Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles) ImplicitResidualDPCM : 1 # Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles) ExplicitResidualDPCM : 1 # Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles) ResidualRotation : 1 # Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles) SingleSignificanceMapContext : 1 # Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles) IntraReferenceSmoothing : 1 # 0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1) GolombRiceParameterAdaptation : 1 # Enable the partial retention of the Golomb-Rice parameter value from one coefficient group to the next HighPrecisionPredictionWeighting : 1 # Use high precision option for weighted prediction (not valid in V1 profiles) CrossComponentPrediction : 1 # Enable the use of cross-component prediction (not valid in V1 profiles) ### DO NOT ADD ANYTHING BELOW THIS LINE ### ### DO NOT DELETE THE EMPTY LINE BELOW ### HM-HM-18.0/cfg/misc/example_colour_remapping_sei_encoder_0.txt000077500000000000000000000035501442026013100243400ustar00rootroot00000000000000# Example colour remapping information SEI configuration file # One of these is required per POC, with the POC number used in the filename suffix. colour_remap_id: 1 colour_remap_cancel_flag: 0 colour_remap_persistence_flag: 1 colour_remap_video_signal_info_present_flag: 1 colour_remap_full_range_flag: 0 colour_remap_primaries: 1 colour_remap_transfer_function: 1 colour_remap_matrix_coefficients: 1 colour_remap_input_bit_depth: 10 colour_remap_bit_depth: 10 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 0 pre_lut_target_value[c][i]: 0 pre_lut_coded_value[c][i]: 1023 pre_lut_target_value[c][i]: 1023 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 0 pre_lut_target_value[c][i]: 0 pre_lut_coded_value[c][i]: 1023 pre_lut_target_value[c][i]: 1023 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 0 pre_lut_target_value[c][i]: 0 pre_lut_coded_value[c][i]: 1023 pre_lut_target_value[c][i]: 1023 colour_remap_matrix_present_flag: 1 log2_matrix_denom: 10 colour_remap_coeffs[c][i]: 1024 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 1024 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 0 colour_remap_coeffs[c][i]: 1024 post_lut_num_val_minus1[c]: 3 post_lut_coded_value[c][i]: 0 post_lut_target_value[c][i]: 0 post_lut_coded_value[c][i]: 200 post_lut_target_value[c][i]: 100 post_lut_coded_value[c][i]: 800 post_lut_target_value[c][i]: 900 post_lut_coded_value[c][i]: 1023 post_lut_target_value[c][i]: 1023 post_lut_num_val_minus1[c]: 1 post_lut_coded_value[c][i]: 0 post_lut_target_value[c][i]: 0 post_lut_coded_value[c][i]: 1023 post_lut_target_value[c][i]: 1023 post_lut_num_val_minus1[c]: 1 post_lut_coded_value[c][i]: 0 post_lut_target_value[c][i]: 0 post_lut_coded_value[c][i]: 1023 post_lut_target_value[c][i]: 1023 HM-HM-18.0/cfg/per-class/000077500000000000000000000000001442026013100146715ustar00rootroot00000000000000HM-HM-18.0/cfg/per-class/classF.cfg000066400000000000000000000000221442026013100165570ustar00rootroot00000000000000TemporalFilter: 0 HM-HM-18.0/cfg/per-class/classH1.cfg000066400000000000000000000012561442026013100166540ustar00rootroot00000000000000#======== Luma adaptive QP ======== LumaLevelToDeltaQPMode : 1 # Change luma delta QP based on average luma #======== Chroma QP scale ============ WCGPPSEnable : 1 # enable WCG Chroma scale #======== VUI Parameters (PQ) ========= #VuiParametersPresent : 1 #VideoSignalTypePresent : 1 #VideoFullRange : 0 #ColourDescriptionPresent : 1 #ColourPrimaries : 9 #TransferCharacteristics : 16 #MatrixCoefficients : 9 #ChromaLocInfoPresent : 1 #ChromaSampleLocTypeTopField : 2 #ChromaSampleLocTypeBottomField : 2HM-HM-18.0/cfg/per-class/classH2.cfg000066400000000000000000000012561442026013100166550ustar00rootroot00000000000000 ======== Luma adaptive QP ======== LumaLevelToDeltaQPMode : 0 # Change luma delta QP based on average luma #======== Chroma QP scale ============ WCGPPSEnable : 0 # enable WCG Chroma scale #======== VUI Parameters (HLG) ======== #VuiParametersPresent : 1 #VideoSignalTypePresent : 1 #VideoFullRange : 0 #ColourDescriptionPresent : 1 #ColourPrimaries : 9 #TransferCharacteristics : 18 #MatrixCoefficients : 9 #ChromaLocInfoPresent : 1 #ChromaSampleLocTypeTopField : 0 #ChromaSampleLocTypeBottomField : 0HM-HM-18.0/cfg/per-sequence-HBD/000077500000000000000000000000001442026013100157675ustar00rootroot00000000000000HM-HM-18.0/cfg/per-sequence-HBD/CrowdRun_RGB_16bit.cfg000066400000000000000000000017521442026013100217170ustar00rootroot00000000000000#======== File I/O =============== InputFile : CrowdRun_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/DucksTakeOff_RGB_16bit.cfg000066400000000000000000000017561442026013100224710ustar00rootroot00000000000000#======== File I/O =============== InputFile : DucksTakeOff_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_BalloonFestival_420_12bit.cfg000066400000000000000000000012361442026013100234540ustar00rootroot00000000000000#======== File I/O =============== InputFile : BalloonFestival_1920x1080p_24_12b_pq_709_ct2020_420.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_BalloonFestival_422_12bit.cfg000066400000000000000000000012361442026013100234560ustar00rootroot00000000000000#======== File I/O =============== InputFile : BalloonFestival_1920x1080p_24_12b_pq_709_ct2020_422.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_BalloonFestival_444_12bit.cfg000066400000000000000000000012361442026013100234620ustar00rootroot00000000000000#======== File I/O =============== InputFile : BalloonFestival_1920x1080p_24_12b_pq_709_ct2020_444.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_FireEater2_420_12bit.cfg000066400000000000000000000012421442026013100223150ustar00rootroot00000000000000#======== File I/O =============== InputFile : FireEater2Clip4000r1_1920x1080p_25_12b_pq_709_ct2020_420.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 25 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_FireEater2_422_12bit.cfg000066400000000000000000000012421442026013100223170ustar00rootroot00000000000000#======== File I/O =============== InputFile : FireEater2Clip4000r1_1920x1080p_25_12b_pq_709_ct2020_422.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 25 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_FireEater2_444_12bit.cfg000066400000000000000000000012421442026013100223230ustar00rootroot00000000000000#======== File I/O =============== InputFile : FireEater2Clip4000r1_1920x1080p_25_12b_pq_709_ct2020_444.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 25 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Hurdles_420_12bit.cfg000066400000000000000000000012341442026013100217740ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_04_Hurdles_1920x1080p_50_12b_pq_709_ct2020_420.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Hurdles_422_12bit.cfg000066400000000000000000000012341442026013100217760ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_04_Hurdles_1920x1080p_50_12b_pq_709_ct2020_422.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Hurdles_444_12bit.cfg000066400000000000000000000012341442026013100220020ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_04_Hurdles_1920x1080p_50_12b_pq_709_ct2020_444.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Market3_420_12bit.cfg000066400000000000000000000012371442026013100216770ustar00rootroot00000000000000#======== File I/O =============== InputFile : Market3Clip4000r2_1920x1080p_50_12b_pq_709_ct2020_420.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 400 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Market3_422_12bit.cfg000066400000000000000000000012371442026013100217010ustar00rootroot00000000000000#======== File I/O =============== InputFile : Market3Clip4000r2_1920x1080p_50_12b_pq_709_ct2020_422.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 400 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Market3_444_12bit.cfg000066400000000000000000000012371442026013100217050ustar00rootroot00000000000000#======== File I/O =============== InputFile : Market3Clip4000r2_1920x1080p_50_12b_pq_709_ct2020_444.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 400 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Starting_420_12bit.cfg000066400000000000000000000012351442026013100221620ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_06_Starting_1920x1080p_50_12b_pq_709_ct2020_420.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Starting_422_12bit.cfg000066400000000000000000000012351442026013100221640ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_06_Starting_1920x1080p_50_12b_pq_709_ct2020_422.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H1_Starting_444_12bit.cfg000066400000000000000000000012351442026013100221700ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBU_06_Starting_1920x1080p_50_12b_pq_709_ct2020_444.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_DayStreet_420_12bit.cfg000066400000000000000000000012171442026013100222740ustar00rootroot00000000000000#======== File I/O =============== InputFile : DayStreet_1920x1080_60p_12bit_420_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_DayStreet_422_12bit.cfg000066400000000000000000000012171442026013100222760ustar00rootroot00000000000000#======== File I/O =============== InputFile : DayStreet_1920x1080_60p_12bit_422_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_DayStreet_444_12bit.cfg000066400000000000000000000012171442026013100223020ustar00rootroot00000000000000#======== File I/O =============== InputFile : DayStreet_1920x1080_60p_12bit_444_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_NightStreet_420_12bit.cfg000066400000000000000000000012211442026013100226230ustar00rootroot00000000000000#======== File I/O =============== InputFile : NightStreet_1920x1080_60p_12bit_420_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_NightStreet_422_12bit.cfg000066400000000000000000000012211442026013100226250ustar00rootroot00000000000000#======== File I/O =============== InputFile : NightStreet_1920x1080_60p_12bit_422_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_NightStreet_444_12bit.cfg000066400000000000000000000012211442026013100226310ustar00rootroot00000000000000#======== File I/O =============== InputFile : NightStreet_1920x1080_60p_12bit_444_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_PeopleInShoppingCenter_420_12bit.cfg000066400000000000000000000012341442026013100247530ustar00rootroot00000000000000#======== File I/O =============== InputFile : PeopleInShoppingCenter_1920x1080_60p_12bit_420_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_PeopleInShoppingCenter_422_12bit.cfg000066400000000000000000000012341442026013100247550ustar00rootroot00000000000000#======== File I/O =============== InputFile : PeopleInShoppingCenter_1920x1080_60p_12bit_422_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_PeopleInShoppingCenter_444_12bit.cfg000066400000000000000000000012341442026013100247610ustar00rootroot00000000000000#======== File I/O =============== InputFile : PeopleInShoppingCenter_1920x1080_60p_12bit_444_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_StainedGlass_420_12bit.cfg000066400000000000000000000012221442026013100227450ustar00rootroot00000000000000#======== File I/O =============== InputFile : StainedGlass_1920x1080_60p_12bit_420_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_StainedGlass_422_12bit.cfg000066400000000000000000000012221442026013100227470ustar00rootroot00000000000000#======== File I/O =============== InputFile : StainedGlass_1920x1080_60p_12bit_422_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/H2_StainedGlass_444_12bit.cfg000066400000000000000000000012221442026013100227530ustar00rootroot00000000000000#======== File I/O =============== InputFile : StainedGlass_1920x1080_60p_12bit_444_hlg.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/InToTree_RGB_16bit.cfg000066400000000000000000000017521442026013100216450ustar00rootroot00000000000000#======== File I/O =============== InputFile : InToTree_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/OldTownCross_RGB_16bit.cfg000066400000000000000000000017561442026013100225600ustar00rootroot00000000000000#======== File I/O =============== InputFile : OldTownCross_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 4.1 HM-HM-18.0/cfg/per-sequence-HBD/ParkJoy_RGB_16bit.cfg000066400000000000000000000017511442026013100215320ustar00rootroot00000000000000#======== File I/O =============== InputFile : ParkJoy_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 4.1 HM-HM-18.0/cfg/per-sequence-HDR/000077500000000000000000000000001442026013100160075ustar00rootroot00000000000000HM-HM-18.0/cfg/per-sequence-HDR/H1_BalloonFestival.cfg000066400000000000000000000023521442026013100221060ustar00rootroot00000000000000#======== File I/O =============== InputFile : BalloonFestival_1920x1080p_25_10b_pq_709_ct2020_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.14 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.79 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_Cosmos1_TreeTrunk.cfg000066400000000000000000000023331442026013100223500ustar00rootroot00000000000000#======== File I/O =============== InputFile : Cosmos1_1920x856_BT2100_PQ_24fps_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 856 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.04 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.39 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_EBU_Hurdles.cfg000066400000000000000000000023471442026013100211270ustar00rootroot00000000000000#======== File I/O =============== InputFile : Hurdles_1920x1080p_50_10b_pq_709_ct2020_420_rev1.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.14 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.79 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_EBU_Starting.cfg000066400000000000000000000023501442026013100213060ustar00rootroot00000000000000#======== File I/O =============== InputFile : Starting_1920x1080p_50_10b_pq_709_ct2020_420_rev1.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.14 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.79 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_Market.cfg000066400000000000000000000023471442026013100202510ustar00rootroot00000000000000#======== File I/O =============== InputFile : Market3_1920x1080p_50_10b_pq_709_ct2020_420_rev1.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 400 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.14 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.79 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_ShowGirl.cfg000066400000000000000000000023561442026013100205640ustar00rootroot00000000000000#======== File I/O =============== InputFile : ShowGirl2TeaserClip4000_1920x1080p_24_12_P3_ct2020_rev1.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 25 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 339 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.04 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.39 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H1_SunRise.cfg000066400000000000000000000023421442026013100204110ustar00rootroot00000000000000#======== File I/O =============== InputFile : SunRise_1920x1080p_25_10b_pq_709_ct2020_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 25 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 4.1 #============ HDR ================ WCGPPSChromaQpScale : -0.46 # Linear chroma QP offset mapping (scale) WCGPPSChromaQpOffset : 9.26 # Linear chroma QP offset mapping (offset) WCGPPSCbQpScale : 1.14 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.14 for BT.709 material and 1.04 for P3 material) WCGPPSCrQpScale : 1.79 # Scale factor depending on capture and representation color space (with BT.2020 container use 1.79 for BT.709 material and 1.39 for P3 material) HM-HM-18.0/cfg/per-sequence-HDR/H2_DayStreet2.cfg000066400000000000000000000012261442026013100210100ustar00rootroot00000000000000#======== File I/O =============== InputFile : DayStreet2_3840x2160_60p_10bit_420_hlg_type2.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence-HDR/H2_FlyingBirds3.cfg000066400000000000000000000012261442026013100213210ustar00rootroot00000000000000#======== File I/O =============== InputFile : FlyingBirds3_3840x2160p_60_10b_HLG_420_type2.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence-HDR/H2_PeopleInShoppingCenter2.cfg000066400000000000000000000012431442026013100234670ustar00rootroot00000000000000#======== File I/O =============== InputFile : PeopleInShoppingCenter2_3840x2160_60p_10bit_420_hlg_type2.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence-HDR/H2_SunsetBeach3.cfg000066400000000000000000000012261442026013100213110ustar00rootroot00000000000000#======== File I/O =============== InputFile : SunsetBeach3_3840x2160p_60_10b_HLG_420_type2.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/000077500000000000000000000000001442026013100153745ustar00rootroot00000000000000HM-HM-18.0/cfg/per-sequence/ArenaOfValor.cfg000066400000000000000000000012151442026013100203730ustar00rootroot00000000000000#======== File I/O =============== InputFile : ArenaOfValor_1920x1080_60_8bit_420.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence/BQMall.cfg000066400000000000000000000012371442026013100171700ustar00rootroot00000000000000#======== File I/O =============== InputFile : BQMall_832x480_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 832 # Input frame width SourceHeight : 480 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded LastValidFrame : 599 Level : 3.1 HM-HM-18.0/cfg/per-sequence/BQSquare.cfg000066400000000000000000000012411442026013100175360ustar00rootroot00000000000000#======== File I/O =============== InputFile : BQSquare_416x240_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 416 # Input frame width SourceHeight : 240 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded LastValidFrame : 599 Level : 2.1 HM-HM-18.0/cfg/per-sequence/BQTerrace.cfg000066400000000000000000000012441442026013100176660ustar00rootroot00000000000000#======== File I/O =============== InputFile : BQTerrace_1920x1080_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded LastValidFrame : 599 Level : 4.1 HM-HM-18.0/cfg/per-sequence/BasketballDrill.cfg000066400000000000000000000012501442026013100211060ustar00rootroot00000000000000#======== File I/O =============== InputFile : BasketballDrill_832x480_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 832 # Input frame width SourceHeight : 480 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 3.1 HM-HM-18.0/cfg/per-sequence/BasketballDrillText.cfg000066400000000000000000000012541442026013100217570ustar00rootroot00000000000000#======== File I/O =============== InputFile : BasketballDrillText_832x480_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 832 # Input frame width SourceHeight : 480 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 3.1 HM-HM-18.0/cfg/per-sequence/BasketballDrive.cfg000066400000000000000000000012521442026013100211130ustar00rootroot00000000000000#======== File I/O =============== InputFile : BasketballDrive_1920x1080_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 4.1 HM-HM-18.0/cfg/per-sequence/BasketballPass.cfg000066400000000000000000000012471442026013100207540ustar00rootroot00000000000000#======== File I/O =============== InputFile : BasketballPass_416x240_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 416 # Input frame width SourceHeight : 240 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 2.1 HM-HM-18.0/cfg/per-sequence/BasketballScreen_444.cfg000066400000000000000000000012171442026013100216550ustar00rootroot00000000000000#======== File I/O =============== InputFile : Basketball_Screen_2560x1440_60p_8b444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 322 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1440 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/BasketballScreen_RGB.cfg000066400000000000000000000017601442026013100217570ustar00rootroot00000000000000#======== File I/O =============== InputFile : Basketball_Screen_2560x1440_60p_8b444.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 322 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1440 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/BirdsInCage_444_10bit.cfg000066400000000000000000000012141442026013100215570ustar00rootroot00000000000000#======== File I/O =============== InputFile : BirdsInCage_1920x1080_60_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/BlowingBubbles.cfg000066400000000000000000000012471442026013100207610ustar00rootroot00000000000000#======== File I/O =============== InputFile : BlowingBubbles_416x240_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 416 # Input frame width SourceHeight : 240 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 2.1 HM-HM-18.0/cfg/per-sequence/Bubbles_RGB_16bit.cfg000066400000000000000000000017511442026013100211360ustar00rootroot00000000000000#======== File I/O =============== InputFile : Bubbles_4096x2160_24_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 4096 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 120 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/CADWaveform_444.cfg000066400000000000000000000012261442026013100205470ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cad_waveform_1920x1080_20_8bit_200_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/CADWaveform_GBR.cfg000066400000000000000000000012231442026013100206430ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cad_waveform_1920x1080_20_8bit_200_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/CADWaveform_RGB.cfg000066400000000000000000000017641442026013100206550ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cad_waveform_1920x1080_20_8bit_200_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Cactus.cfg000066400000000000000000000011751442026013100173030ustar00rootroot00000000000000#======== File I/O =============== InputFile : Cactus_1920x1080_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 4.1 HM-HM-18.0/cfg/per-sequence/Campfire.cfg000066400000000000000000000012351442026013100176040ustar00rootroot00000000000000#======== File I/O =============== InputFile : Campfire_3840x2160_30fps_10bit_420_bt709_videoRange.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/Cardiac_400_12bit.cfg000066400000000000000000000012061442026013100207660ustar00rootroot00000000000000#======== File I/O =============== InputFile : CT_Cardiac_512x512_12bit_400.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 400 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 512 # Input frame width SourceHeight : 512 # Input frame height FramesToBeEncoded : 281 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/CatRobot.cfg000066400000000000000000000012211442026013100175660ustar00rootroot00000000000000#======== File I/O =============== InputFile : CatRobot_3840x2160_60fps_10bit_420_jvet.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/CatRobot1.cfg000066400000000000000000000012141442026013100176510ustar00rootroot00000000000000#======== File I/O =============== InputFile : CatRobot1_3840x2160p_60_10_709_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/ChinaSpeed.cfg000066400000000000000000000012001442026013100200510ustar00rootroot00000000000000#======== File I/O =============== InputFile : ChinaSpeed_1024x768_30.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1024 # Input frame width SourceHeight : 768 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 3.1 HM-HM-18.0/cfg/per-sequence/Console_444.cfg000066400000000000000000000012121442026013100200460ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_console_1920x1080_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Console_RGB.cfg000066400000000000000000000017531442026013100201570ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_console_1920x1080_60_8bit_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/CrowdRun_444_10bit.cfg000066400000000000000000000012111442026013100212050ustar00rootroot00000000000000#======== File I/O =============== InputFile : CrowdRun_1920x1080_50_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/CrowdRun_RGB_16bit.cfg000066400000000000000000000017521442026013100213240ustar00rootroot00000000000000#======== File I/O =============== InputFile : CrowdRun_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/DaylightRoad2.cfg000066400000000000000000000012211442026013100205060ustar00rootroot00000000000000#======== File I/O =============== InputFile : DaylightRoad2_3840x2160_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/Desktop_444.cfg000066400000000000000000000012121442026013100200550ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_desktop_1920x1080_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Desktop_RGB.cfg000066400000000000000000000017531442026013100201660ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_desktop_1920x1080_60_8bit_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Doc_444.cfg000066400000000000000000000012111442026013100171500ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_doc_1280x720_10_8bit_500_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 10 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Doc_RGB.cfg000066400000000000000000000017461442026013100172640ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_doc_1280x720_10_8bit_500.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 10 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Drums100.cfg000066400000000000000000000012201442026013100173630ustar00rootroot00000000000000#======== File I/O =============== InputFile : Drums_3840x2160_100fps_10bit_420_jvet.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 100 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.2 HM-HM-18.0/cfg/per-sequence/DucksAndLegs_RGB_10bit.cfg000066400000000000000000000017571442026013100220670ustar00rootroot00000000000000#======== File I/O =============== InputFile : DucksAndLegs_1920x1080_30_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/DucksTakeOff_RGB_16bit.cfg000066400000000000000000000017561442026013100220760ustar00rootroot00000000000000#======== File I/O =============== InputFile : DucksTakeOff_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBUGraphics_422_10bit.cfg000066400000000000000000000012141442026013100215350ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBUGraphics_1920x1080_50_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBUHorse_422_10bit.cfg000066400000000000000000000012111442026013100210520ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBUHorse_1920x1080_50_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBUKidsSoccer_422_10bit.cfg000066400000000000000000000012161442026013100220300ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBUKidsSoccer_1920x1080_50_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBULupoCandlelight_444_10bit.cfg000066400000000000000000000012231442026013100230570ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBULupoCandlelight_1920x1080_50_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBULupoCandlelight_RGB_10bit.cfg000066400000000000000000000017651442026013100231710ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBULupoCandlelight_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBURainFruits_444_10bit.cfg000066400000000000000000000012161442026013100220710ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBURainFruits_1920x1080_50_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBURainFruits_RGB_10bit+2MSB.cfg000066400000000000000000000020771442026013100226750ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBURainFruits_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 12 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBURainFruits_RGB_10bit+4MSB.cfg000066400000000000000000000020771442026013100226770ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBURainFruits_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 14 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBURainFruits_RGB_10bit+6MSB.cfg000066400000000000000000000020771442026013100227010ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBURainFruits_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 16 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBURainFruits_RGB_10bit.cfg000066400000000000000000000017601442026013100221740ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBURainFruits_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/EBUWaterRocksClose_422_10bit.cfg000066400000000000000000000012231442026013100230470ustar00rootroot00000000000000#======== File I/O =============== InputFile : EBUWaterRocksClose_1920x1080_50_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/FlyingGraphics_444.cfg000066400000000000000000000012211442026013100213550ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_flyingGraphics_1920x1080_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/FlyingGraphics_RGB.cfg000066400000000000000000000017621442026013100214660ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_flyingGraphics_1920x1080_60_8bit_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/FoodMarket4.cfg000066400000000000000000000012171442026013100201750ustar00rootroot00000000000000#======== File I/O =============== InputFile : FoodMarket4_3840x2160_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/FourPeople.cfg000066400000000000000000000011761442026013100201420ustar00rootroot00000000000000#======== File I/O =============== InputFile : FourPeople_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/FruitStall_RGB_16bit.cfg000066400000000000000000000017541442026013100216540ustar00rootroot00000000000000#======== File I/O =============== InputFile : FruitStall_1920x1080_24_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Head_400_16bit.cfg000066400000000000000000000012041442026013100203030ustar00rootroot00000000000000#======== File I/O =============== InputFile : AX_Head_1240x960_16bit_400.yuv InputBitDepth : 16 # Input bitdepth InputChromaFormat : 400 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1240 # Input frame width SourceHeight : 960 # Input frame height FramesToBeEncoded : 496 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/InToTree_RGB_16bit.cfg000066400000000000000000000017521442026013100212520ustar00rootroot00000000000000#======== File I/O =============== InputFile : InToTree_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Johnny.cfg000066400000000000000000000011721442026013100173230ustar00rootroot00000000000000#======== File I/O =============== InputFile : Johnny_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Kimono.cfg000066400000000000000000000011741442026013100173140ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Kimono_422_10bit.cfg000066400000000000000000000012101442026013100206710ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Kimono_444_10bit.cfg000066400000000000000000000012101442026013100206750ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Kimono_RGB_10bit+2MSB.cfg000066400000000000000000000020711442026013100215010ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 12 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Kimono_RGB_10bit+4MSB.cfg000066400000000000000000000020711442026013100215030ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 14 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Kimono_RGB_10bit+6MSB.cfg000066400000000000000000000020711442026013100215050ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_444.rgb InputBitDepth : 10 # Input bitdepth MSBExtendedBitDepth : 16 # bit depth after addition of MSBs InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Kimono_RGB_10bit.cfg000066400000000000000000000017521442026013100210070ustar00rootroot00000000000000#======== File I/O =============== InputFile : Kimono1_1920x1080_24_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/KristenAndSara.cfg000066400000000000000000000012021442026013100207210ustar00rootroot00000000000000#======== File I/O =============== InputFile : KristenAndSara_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/LongRunShort_400_12bit.cfg000066400000000000000000000012131442026013100220420ustar00rootroot00000000000000#======== File I/O =============== InputFile : CT_LongrunShort_512x512_12bit_400.yuv InputBitDepth : 12 # Input bitdepth InputChromaFormat : 400 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 512 # Input frame width SourceHeight : 512 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Map_444.cfg000066400000000000000000000012051442026013100171630ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_map_1280x720_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Map_GBR.cfg000066400000000000000000000012011442026013100172560ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_map_1280x720_60_8bit.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Map_RGB.cfg000066400000000000000000000017421442026013100172700ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_map_1280x720_60_8bit.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/MarketPlace.cfg000066400000000000000000000012151442026013100202440ustar00rootroot00000000000000#======== File I/O =============== InputFile : MarketPlace_1920x1080_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/MissionControl2_444.cfg000066400000000000000000000012211442026013100215100ustar00rootroot00000000000000#======== File I/O =============== InputFile : MissionControlClip2_2560x1440_60p_8b444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 120 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1440 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/MissionControl2_RGB.cfg000066400000000000000000000017621442026013100216210ustar00rootroot00000000000000#======== File I/O =============== InputFile : MissionControlClip2_2560x1440_60p_8b444.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 120 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1440 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/MissionControl3_444.cfg000066400000000000000000000012211442026013100215110ustar00rootroot00000000000000#======== File I/O =============== InputFile : MissionControlClip3_1920x1080_60p_8b444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/MissionControl3_RGB.cfg000066400000000000000000000017621442026013100216220ustar00rootroot00000000000000#======== File I/O =============== InputFile : MissionControlClip3_1920x1080_60p_8b444.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/NebutaFestival_10bit.cfg000066400000000000000000000012621442026013100217710ustar00rootroot00000000000000#======== File I/O =============== InputFile : NebutaFestival_2560x1600_60_10bit_crop.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded LastValidFrame : 299 Level : 5 HM-HM-18.0/cfg/per-sequence/OldTownCross_RGB_10bit.cfg000066400000000000000000000017571442026013100221600ustar00rootroot00000000000000#======== File I/O =============== InputFile : OldTownCross_1920x1080_50_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/OldTownCross_RGB_16bit.cfg000066400000000000000000000017561442026013100221650ustar00rootroot00000000000000#======== File I/O =============== InputFile : OldTownCross_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/PCBLayout_444.cfg000066400000000000000000000012241442026013100202510ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_pcb_layout_1920x1080_20_8bit_200_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/PCBLayout_GBR.cfg000066400000000000000000000012211442026013100203450ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_pcb_layout_1920x1080_20_8bit_200_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/PCBLayout_RGB.cfg000066400000000000000000000017621442026013100203570ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_pcb_layout_1920x1080_20_8bit_200_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/ParkJoy_RGB_16bit.cfg000066400000000000000000000017511442026013100211370ustar00rootroot00000000000000#======== File I/O =============== InputFile : ParkJoy_1920x1080_50_16bit_444.rgb InputBitDepth : 16 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/ParkRunning3.cfg000066400000000000000000000012201442026013100203710ustar00rootroot00000000000000#======== File I/O =============== InputFile : ParkRunning3_3840x2160_50fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/ParkScene.cfg000066400000000000000000000011761442026013100177350ustar00rootroot00000000000000#======== File I/O =============== InputFile : ParkScene_1920x1080_24.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/ParkScene_RGB_10bit.cfg000066400000000000000000000017541442026013100214300ustar00rootroot00000000000000#======== File I/O =============== InputFile : ParkScene_1920x1080_24_10bit_444.rgb InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 24 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 240 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/PartyScene.cfg000066400000000000000000000012431442026013100201320ustar00rootroot00000000000000#======== File I/O =============== InputFile : PartyScene_832x480_50.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 832 # Input frame width SourceHeight : 480 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded LastValidFrame : 499 Level : 3.1 HM-HM-18.0/cfg/per-sequence/PeopleOnStreet.cfg000066400000000000000000000012101442026013100207570ustar00rootroot00000000000000#======== File I/O =============== InputFile : PeopleOnStreet_2560x1600_30_crop.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 150 # Number of frames to be coded Level : 5 HM-HM-18.0/cfg/per-sequence/Programming_444.cfg000066400000000000000000000012151442026013100207310ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_programming_1280x720_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Programming_GBR.cfg000066400000000000000000000012111442026013100210240ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_programming_1280x720_60_8bit.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Programming_RGB.cfg000066400000000000000000000017521442026013100210360ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_programming_1280x720_60_8bit.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/RaceHorses.cfg000066400000000000000000000011751442026013100201170ustar00rootroot00000000000000#======== File I/O =============== InputFile : RaceHorses_416x240_30.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 416 # Input frame width SourceHeight : 240 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 2 HM-HM-18.0/cfg/per-sequence/RaceHorsesC.cfg000066400000000000000000000011751442026013100202220ustar00rootroot00000000000000#======== File I/O =============== InputFile : RaceHorses_832x480_30.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 832 # Input frame width SourceHeight : 480 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 3 HM-HM-18.0/cfg/per-sequence/RitualDance.cfg000066400000000000000000000012151442026013100202470ustar00rootroot00000000000000#======== File I/O =============== InputFile : RitualDance_1920x1080_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Robot_444.cfg000066400000000000000000000012131442026013100175320ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_robot_1280x720_30_8bit_300_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Robot_RGB.cfg000066400000000000000000000017501442026013100176370ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_robot_1280x720_30_8bit_300.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Rollercoaster2.cfg000066400000000000000000000012221442026013100207540ustar00rootroot00000000000000#======== File I/O =============== InputFile : RollerCoaster2_3840x2160_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/Seeking_422_10bit.cfg000066400000000000000000000012101442026013100210220ustar00rootroot00000000000000#======== File I/O =============== InputFile : Seeking_1920x1080_50_10bit_422.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 50 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/SlideEditing.cfg000066400000000000000000000012021442026013100204140ustar00rootroot00000000000000#======== File I/O =============== InputFile : SlideEditing_1280x720_30.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 3.1 HM-HM-18.0/cfg/per-sequence/SlideShow.cfg000066400000000000000000000011771442026013100177640ustar00rootroot00000000000000#======== File I/O =============== InputFile : SlideShow_1280x720_20.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 3.1 HM-HM-18.0/cfg/per-sequence/SlideShow_444.cfg000066400000000000000000000012171442026013100203520ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_SlideShow_1280x720_20_8bit_500_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/SlideShow_RGB.cfg000066400000000000000000000017541442026013100204570ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_SlideShow_1280x720_20_8bit_500.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/SocialNetworkMap_444.cfg000066400000000000000000000012671442026013100217000ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_socialNetworkMap_1920x1080_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded LastValidFrame : 599 Level : 6.2 HM-HM-18.0/cfg/per-sequence/SocialNetworkMap_RGB.cfg000066400000000000000000000020301442026013100217640ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_socialNetworkMap_1920x1080_60_8bit_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded LastValidFrame : 599 InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/SteamLocomotiveTrain_10bit.cfg000066400000000000000000000012701442026013100231640ustar00rootroot00000000000000#======== File I/O =============== InputFile : SteamLocomotiveTrain_2560x1600_60_10bit_crop.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded LastValidFrame : 299 Level : 5 HM-HM-18.0/cfg/per-sequence/Tango2.cfg000066400000000000000000000012121442026013100172030ustar00rootroot00000000000000#======== File I/O =============== InputFile : Tango2_3840x2160_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 294 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/ToddlerFountain2.cfg000066400000000000000000000012241442026013100212370ustar00rootroot00000000000000#======== File I/O =============== InputFile : ToddlerFountain2_3840x2160_60fps_10bit_420.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5.1 HM-HM-18.0/cfg/per-sequence/Traffic.cfg000066400000000000000000000012011442026013100174250ustar00rootroot00000000000000#======== File I/O =============== InputFile : Traffic_2560x1600_30_crop.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 150 # Number of frames to be coded Level : 5 HM-HM-18.0/cfg/per-sequence/TrafficFlow.cfg000066400000000000000000000012221442026013100202600ustar00rootroot00000000000000#======== File I/O =============== InputFile : TrafficFlow_3840x2160_30fps_10bit_420_jvet.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 3840 # Input frame width SourceHeight : 2160 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 5 HM-HM-18.0/cfg/per-sequence/Traffic_422_10bit.cfg000066400000000000000000000012151442026013100210200ustar00rootroot00000000000000#======== File I/O =============== InputFile : Traffic_2560x1600_30_10bit_422_crop.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 422 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 150 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Traffic_444_10bit.cfg000066400000000000000000000012151442026013100210240ustar00rootroot00000000000000#======== File I/O =============== InputFile : Traffic_2560x1600_30_10bit_444_crop.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 150 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Traffic_RGB_12bit.cfg000066400000000000000000000017521442026013100211330ustar00rootroot00000000000000#======== File I/O =============== InputFile : Traffic_2560x1600_30_12bit_444.rgb InputBitDepth : 12 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 2560 # Input frame width SourceHeight : 1600 # Input frame height FramesToBeEncoded : 150 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/TwistTunnel_444.cfg000066400000000000000000000012301442026013100207440ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cg_twist_tunnel_1280x720_30_8bit_300_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/TwistTunnel_GBR.cfg000066400000000000000000000012211442026013100210430ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cg_twist_tunnel_1280x720_30_8bit_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/TwistTunnel_RGB.cfg000066400000000000000000000017621442026013100210550ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_cg_twist_tunnel_1280x720_30_8bit_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/VenueVu_444_10bit.cfg000066400000000000000000000012101442026013100210360ustar00rootroot00000000000000#======== File I/O =============== InputFile : VenueVu_1920x1080_30_10bit_444.yuv InputBitDepth : 10 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/VenueVu_GBR.cfg000066400000000000000000000012131442026013100201410ustar00rootroot00000000000000#======== File I/O =============== InputFile : VenueVu_1920x1080_30_8bit_444_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/VenueVu_RGB.cfg000066400000000000000000000017511442026013100201500ustar00rootroot00000000000000#======== File I/O =============== InputFile : VenueVu_1920x1080_30_8bit_444.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/VideoConferencingDocSharing_444.cfg000066400000000000000000000012471442026013100240050ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_video_conferencing_doc_sharing_1280x720_30_8bit_300_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/VideoConferencingDocSharing_GBR.cfg000066400000000000000000000012441442026013100241010ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_video_conferencing_doc_sharing_1280x720_30_8bit_300_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/VideoConferencingDocSharing_RGB.cfg000066400000000000000000000020051442026013100240750ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_video_conferencing_doc_sharing_1280x720_30_8bit_300_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Vidyo1.cfg000066400000000000000000000011721442026013100172310ustar00rootroot00000000000000#======== File I/O =============== InputFile : vidyo1_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Vidyo3.cfg000066400000000000000000000011721442026013100172330ustar00rootroot00000000000000#======== File I/O =============== InputFile : vidyo3_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Vidyo4.cfg000066400000000000000000000011721442026013100172340ustar00rootroot00000000000000#======== File I/O =============== InputFile : vidyo4_1280x720_60.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 420 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 4 HM-HM-18.0/cfg/per-sequence/Viking_444.cfg000066400000000000000000000012141442026013100176750ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_viking_1280x720_30_8bit_300_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Viking_RGB.cfg000066400000000000000000000017511442026013100200020ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_viking_1280x720_30_8bit_300.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/WebBrowsing_444.cfg000066400000000000000000000012251442026013100207000ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_web_browsing_1280x720_30_8bit_300_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/WebBrowsing_GBR.cfg000066400000000000000000000012221442026013100207740ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_web_browsing_1280x720_30_8bit_300_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/WebBrowsing_RGB.cfg000066400000000000000000000017631442026013100210060ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_web_browsing_1280x720_30_8bit_300_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 30 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 300 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/Web_444.cfg000066400000000000000000000012111442026013100171600ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_Web_1280x720_10_8bit_500_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 10 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/Web_RGB.cfg000066400000000000000000000017461442026013100172740ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_Web_1280x720_10_8bit_500.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 10 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 500 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/WordEditing_444.cfg000066400000000000000000000012151442026013100206660ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_wordEditing_1280x720_60_8bit_444.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/WordEditing_GBR.cfg000066400000000000000000000012111442026013100207610ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_wordEditing_1280x720_60_8bit.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/WordEditing_RGB.cfg000066400000000000000000000017521442026013100207730ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_wordEditing_1280x720_60_8bit.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 60 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1280 # Input frame width SourceHeight : 720 # Input frame height FramesToBeEncoded : 600 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/per-sequence/ppt_doc_xls_444.cfg000066400000000000000000000012251442026013100207660ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_ppt_doc_xls_1920x1080_20_8bit_200_444_r1.yuv InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/ppt_doc_xls_GBR.cfg000066400000000000000000000012221442026013100210620ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_ppt_doc_xls_1920x1080_20_8bit_200_gbr.gbr InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded Level : 6.2 HM-HM-18.0/cfg/per-sequence/ppt_doc_xls_RGB.cfg000066400000000000000000000017631442026013100210740ustar00rootroot00000000000000#======== File I/O =============== InputFile : sc_ppt_doc_xls_1920x1080_20_8bit_200_rgb.rgb InputBitDepth : 8 # Input bitdepth InputChromaFormat : 444 # Ratio of luminance to chrominance samples FrameRate : 20 # Frame Rate per second FrameSkip : 0 # Number of frames to be skipped in input SourceWidth : 1920 # Input frame width SourceHeight : 1080 # Input frame height FramesToBeEncoded : 200 # Number of frames to be coded InputColourSpaceConvert : RGBtoGBR # Non-normative colour space conversion to apply to input video SNRInternalColourSpace : 1 # Evaluate SNRs in GBR order OutputInternalColourSpace : 0 # Convert recon output back to RGB order. Use --OutputColourSpaceConvert GBRtoRGB on decoder to produce a matching output file. Level : 6.2 HM-HM-18.0/cfg/sei/000077500000000000000000000000001442026013100135605ustar00rootroot00000000000000HM-HM-18.0/cfg/sei/JCTVC-AD0021(JVET-T0056).cfg000066400000000000000000000003121442026013100172210ustar00rootroot00000000000000# Controls if SEI Manifest SEI messages | enabled SEISEIManifestEnabled: 1 # Controls if SEI Prefix Indication SEI messages | enabled SEISEIPrefixIndicationEnabled: 1 HM-HM-18.0/cfg/sei/ambient_viewing_environment.cfg000066400000000000000000000004051442026013100220330ustar00rootroot00000000000000#======== Ambient viewing environment SEI message ===================== SEIAVEEnabled : 1 SEIAVEAmbientIlluminance : 100000 SEIAVEAmbientLightX : 15635 SEIAVEAmbientLightY : 16450 HM-HM-18.0/cfg/sei/annotated_regions/000077500000000000000000000000001442026013100172635ustar00rootroot00000000000000HM-HM-18.0/cfg/sei/annotated_regions/anno_reg_0.txt000066400000000000000000000023451442026013100220370ustar00rootroot00000000000000SEIArCancelFlag: 0 SEIArNotOptForViewingFlag: 0 SEIArTrueMotionFlag: 0 SEIArOccludedObjsFlag: 0 SEIArPartialObjsFlagPresentFlag: 0 SEIArObjLabelPresentFlag: 1 SEIArObjConfInfoPresentFlag: 1 SEIArObjDetConfLength: 7 SEIArObjLabelLangPresentFlag: 1 SEIArLabelLanguage: ENGLISH SEIArNumLabelUpdates: 2 SEIArLabelIdc[c]: 0 SEIArLabelCancelFlag[c]: 0 SEIArLabel[c]: car SEIArLabelIdc[c]: 1 SEIArLabelCancelFlag[c]: 0 SEIArLabel[c]: person SEIArNumObjUpdates: 3 SEIArObjIdx[c]: 0 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 1 SEIArObjectLabelIdc[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 10 SEIArObjLeft[c]: 10 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 1 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 1 SEIArObjectLabelIdc[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 100 SEIArObjLeft[c]: 100 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 2 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 1 SEIArObjectLabelIdc[c]: 1 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 200 SEIArObjLeft[c]: 200 SEIArObjWidth[c]: 80 SEIArObjHeight[c]: 100 SEIArObjDetConf[c]: 85 HM-HM-18.0/cfg/sei/annotated_regions/anno_reg_1.txt000066400000000000000000000014721442026013100220400ustar00rootroot00000000000000SEIArCancelFlag: 0 SEIArNotOptForViewingFlag: 0 SEIArTrueMotionFlag: 0 SEIArOccludedObjsFlag: 0 SEIArPartialObjsFlagPresentFlag: 0 SEIArObjLabelPresentFlag: 1 SEIArObjConfInfoPresentFlag: 1 SEIArObjDetConfLength: 7 SEIArObjLabelLangPresentFlag: 1 SEIArLabelLanguage: ENGLISH SEIArNumLabelUpdates: 0 SEIArNumObjUpdates: 2 SEIArObjIdx[c]: 0 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 20 SEIArObjLeft[c]: 20 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 3 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 1 SEIArObjectLabelIdc[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 300 SEIArObjLeft[c]: 300 SEIArObjWidth[c]: 80 SEIArObjHeight[c]: 100 SEIArObjDetConf[c]: 90 HM-HM-18.0/cfg/sei/annotated_regions/anno_reg_2.txt000066400000000000000000000021561442026013100220410ustar00rootroot00000000000000SEIArCancelFlag: 0 SEIArNotOptForViewingFlag: 0 SEIArTrueMotionFlag: 0 SEIArOccludedObjsFlag: 0 SEIArPartialObjsFlagPresentFlag: 0 SEIArObjLabelPresentFlag: 1 SEIArObjConfInfoPresentFlag: 1 SEIArObjDetConfLength: 7 SEIArObjLabelLangPresentFlag: 1 SEIArLabelLanguage: ENGLISH SEIArNumLabelUpdates: 1 SEIArLabelIdc[c]: 2 SEIArLabelCancelFlag[c]: 0 SEIArLabel[c]: dog SEIArNumObjUpdates: 3 SEIArObjIdx[c]: 1 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 150 SEIArObjLeft[c]: 150 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 2 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 220 SEIArObjLeft[c]: 220 SEIArObjWidth[c]: 80 SEIArObjHeight[c]: 100 SEIArObjDetConf[c]: 85 SEIArObjIdx[c]: 4 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 1 SEIArObjectLabelIdc[c]: 2 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 400 SEIArObjLeft[c]: 400 SEIArObjWidth[c]: 30 SEIArObjHeight[c]: 60 SEIArObjDetConf[c]: 25 HM-HM-18.0/cfg/sei/annotated_regions/anno_reg_3.txt000066400000000000000000000012111442026013100220310ustar00rootroot00000000000000SEIArCancelFlag: 0 SEIArNotOptForViewingFlag: 0 SEIArTrueMotionFlag: 0 SEIArOccludedObjsFlag: 0 SEIArPartialObjsFlagPresentFlag: 0 SEIArObjLabelPresentFlag: 1 SEIArObjConfInfoPresentFlag: 1 SEIArObjDetConfLength: 7 SEIArObjLabelLangPresentFlag: 1 SEIArLabelLanguage: ENGLISH SEIArNumLabelUpdates: 1 SEIArLabelIdc[c]: 2 SEIArLabelCancelFlag[c]: 1 SEIArNumObjUpdates: 2 SEIArObjIdx[c]: 0 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 30 SEIArObjLeft[c]: 30 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 4 SEIArObjCancelFlag[c]: 1 HM-HM-18.0/cfg/sei/annotated_regions/anno_reg_4.txt000066400000000000000000000011341442026013100220360ustar00rootroot00000000000000SEIArCancelFlag: 0 SEIArNotOptForViewingFlag: 0 SEIArTrueMotionFlag: 0 SEIArOccludedObjsFlag: 0 SEIArPartialObjsFlagPresentFlag: 0 SEIArObjLabelPresentFlag: 1 SEIArObjConfInfoPresentFlag: 1 SEIArObjDetConfLength: 7 SEIArObjLabelLangPresentFlag: 1 SEIArLabelLanguage: ENGLISH SEIArNumLabelUpdates: 0 SEIArNumObjUpdates: 2 SEIArObjIdx[c]: 1 SEIArObjCancelFlag[c]: 0 SEIArObjLabelUpdateFlag[c]: 0 SEIArBoundBoxUpdateFlag[c]: 1 SEIArBoundBoxCancelFlag[c]: 0 SEIArObjTop[c]: 180 SEIArObjLeft[c]: 180 SEIArObjWidth[c]: 50 SEIArObjHeight[c]: 50 SEIArObjDetConf[c]: 90 SEIArObjIdx[c]: 3 SEIArObjCancelFlag[c]: 1 HM-HM-18.0/cfg/sei/content_colour_volume.cfg000066400000000000000000000014411442026013100206650ustar00rootroot00000000000000#======== Content Colour Volume SEI message ===================== SEICCVEnabled : 1 SEICCVCancelFlag : 0 SEICCVPersistenceFlag : 1 SEICCVPrimariesPresent : 1 m_ccvSEIPrimariesX0 : 0.300 m_ccvSEIPrimariesY0 : 0.600 m_ccvSEIPrimariesX1 : 0.150 m_ccvSEIPrimariesY1 : 0.060 m_ccvSEIPrimariesX2 : 0.640 m_ccvSEIPrimariesY2 : 0.330 SEICCVMinLuminanceValuePresent : 1 SEICCVMinLuminanceValue : 0.0 SEICCVMaxLuminanceValuePresent : 1 SEICCVMaxLuminanceValue : 0.1 SEICCVAvgLuminanceValuePresent : 1 SEICCVAvgLuminanceValue : 0.01 HM-HM-18.0/cfg/sei/content_light_level.cfg000066400000000000000000000003071442026013100202710ustar00rootroot00000000000000#======== Content Light Level SEI message ===================== SEICLLEnabled : 1 SEICLLMaxContentLightLevel : 4000 SEICLLMaxPicAvgLightLevel : 0 HM-HM-18.0/cfg/sei/equirectangular.cfg000066400000000000000000000006001442026013100174300ustar00rootroot00000000000000#======== Equirectangular Projection SEI message ===================== SEIErpEnabled : 1 SEIErpCancelFlag : 0 SEIErpPersistenceFlag : 1 SEIErpGuardBandFlag : 1 SEIErpGuardBandType : 0 SEIErpLeftGuardBandWidth : 254 SEIErpRightGuardBandWidth : 254 HM-HM-18.0/cfg/sei/film_grain_characteristics_analysis.cfg000066400000000000000000000010511442026013100235030ustar00rootroot00000000000000#======== Film grain characteristics SEI message ===================== SEIFGCEnabled : 1 SEIFGCAnalysisEnabled : 1 SEIFGCCancelFlag : 0 SEIFGCPersistenceFlag : 1 SEIFGCPerPictureSEI : 0 SEIFGCModelID : 0 SEIFGCSepColourDescPresentFlag : 0 SEIFGCBlendingModeID : 0 SEIFGCCompModelPresentComp0 : 1 SEIFGCCompModelPresentComp1 : 0 SEIFGCCompModelPresentComp2 : 0HM-HM-18.0/cfg/sei/film_grain_characterstics.cfg000066400000000000000000000066341442026013100214430ustar00rootroot00000000000000#======== Film grain characteristics SEI message ===================== SEIFGCEnabled : 1 # enable to use FGC SEI message. SEIFGCAnalysisEnabled : 0 # enable film grain analysis to estimate grain parameters. SEIFGCCancelFlag : 0 # for SMPTE-RDD5: the value must be 0 SEIFGCPersistenceFlag : 1 # for SMPTE-RDD5: the value must be 0; When FGC SEI frequency is once per I-period (SEIFGCPerPictureSEI is 0), than SEIFGCPersistenceFlag 1 SEIFGCPerPictureSEI : 0 # for SMPTE-RDD5: the value must be 1 (0: FGC SEI is inserted once per I-period; 1: FGC SEI is inserted once per picture) SEIFGCModelID : 0 # for SMPTE-RDD5: the value must be 0 (0: frequency filtering; 1: auto-regression; 2-3 are reserved) SEIFGCSepColourDescPresentFlag : 0 # for SMPTE-RDD5: the value must be 0 (if not 0, need to specify separate colour description (not implemented in current encoder cmd line)) SEIFGCBlendingModeID : 0 # for SMPTE-RDD5: the value must be 0 (0: additive; 1: multipliciative) SEIFGCLog2ScaleFactor : 2 SEIFGCCompModelPresentComp0 : 1 # if not 0, need to specify model for comp 0; otherwise default parameters will be used. SEIFGCCompModelPresentComp1 : 1 # if not 0, need to specify model for comp 1; otherwise default parameters will be used. SEIFGCCompModelPresentComp2 : 1 # if not 0, need to specify model for comp 2; otherwise default parameters will be used. SEIFGCNumIntensityIntervalMinus1Comp0 : 0 # Number of intensity intervals minus 1 for comp 0 SEIFGCNumIntensityIntervalMinus1Comp1 : 0 # Number of intensity intervals minus 1 for comp 1 SEIFGCNumIntensityIntervalMinus1Comp2 : 0 # Number of intensity intervals minus 1 for comp 2 SEIFGCNumModelValuesMinus1Comp0 : 2 # Number of model values minus 1 for comp 0 SEIFGCNumModelValuesMinus1Comp1 : 2 # Number of model values minus 1 for comp 1 SEIFGCNumModelValuesMinus1Comp2 : 2 # Number of model values minus 1 for comp 2 SEIFGCIntensityIntervalLowerBoundComp0 : 10 # Lower bound of intensity interval for comp 0 (for SMPTE-RDD5, non-overlapping interval) SEIFGCIntensityIntervalLowerBoundComp1 : 60 # Lower bound of intensity interval for comp 1 (for SMPTE-RDD5, non-overlapping interval) SEIFGCIntensityIntervalLowerBoundComp2 : 60 # Lower bound of intensity interval for comp 2 (for SMPTE-RDD5, non-overlapping interval) SEIFGCIntensityIntervalUpperBoundComp0 : 250 # Upper bound of intensity interval for comp 0 (for SMPTE-RDD5, non-overlapping interval) SEIFGCIntensityIntervalUpperBoundComp1 : 200 # Upper bound of intensity interval for comp 1 (for SMPTE-RDD5, non-overlapping interval) SEIFGCIntensityIntervalUpperBoundComp2 : 250 # Upper bound of intensity interval for comp 2 (for SMPTE-RDD5, non-overlapping interval) SEIFGCCompModelValuesComp0 : 16 8 8 # model values for each intensity interval for comp 0 (sigma, h, v (h,v might be inferred based on number of model value)) SEIFGCCompModelValuesComp1 : 24 12 12 # model values for each intensity interval for comp 1 (sigma, h, v (h,v might be inferred based on number of model value)) SEIFGCCompModelValuesComp2 : 40 3 3 # model values for each intensity interval for comp 2 (sigma, h, v (h,v might be inferred based on number of model value)) HM-HM-18.0/cfg/sei/fisheye_video.cfg000066400000000000000000000016411442026013100170650ustar00rootroot00000000000000#======== Fisheye Video Information SEI message ===================== SEIFviEnabled : 1 SEIFviCancelFlag : 0 SEIFviPersistenceFlag : 1 SEIFviViewDimensionIdc : 0 SEIFviNumActiveAreasMinus1 : 1 SEIFviCircularRegionCentreX : 480 1440 SEIFviCircularRegionCentreY : 480 480 SEIFviRectRegionTop : 0 0 SEIFviRectRegionLeft : 0 960 SEIFviRectRegionWidth : 960 960 SEIFviRectRegionHeight : 960 960 SEIFviCircularRegionRadius : 480 480 SEIFviSceneRadius : 460 450 SEIFviCameraCentreAzimuth : 0 -11796480 SEIFviCameraCentreElevation : 0 0 SEIFviCameraCentreTilt : 0 0 SEIFviCameraCentreOffsetX : 0 0 SEIFviCameraCentreOffsetY : 0 0 SEIFviCameraCenterOffsetZ : 0 0 SEIFviFieldOfView : 180 180 SEIFviNumPolynomialCoeffs : 0 0 HM-HM-18.0/cfg/sei/omni_viewport.cfg000066400000000000000000000011231442026013100171370ustar00rootroot00000000000000#======== Omni Viewport SEI message ===================== SEIOmniViewportEnabled : 1 SEIOmniViewportId : 0 SEIOmniViewportCancelFlag : 0 SEIOmniViewportPersistenceFlag : 1 SEIOmniViewportCntMinus1 : 2 SEIOmniViewportAzimuthCentre : -5898240 5898240 0 SEIOmniViewportElevationCentre : -5898240 5898240 0 SEIOmniViewportTiltCentre : -11796480 5898240 0 SEIOmniViewportHorRange : 2949120 2949120 2949120 SEIOmniViewportVerRange : 2949120 2949120 2949120 HM-HM-18.0/cfg/sei/region_wise_packing.cfg000066400000000000000000000027351442026013100202560ustar00rootroot00000000000000#======== Region-wise packing SEI message ===================== SEIRwpEnabled : 1 SEIRwpCancelFlag : 0 SEIRwpPersistenceFlag : 1 SEIRwpConstituentPictureMatchingFlag : 1 SEIRwpNumPackedRegions : 6 SEIRwpProjPictureWidth : 2048 SEIRwpProjPictureHeight : 1024 SEIRwpPackedPictureWidth : 1536 SEIRwpPackedPictureHeight : 768 SEIRwpTransformType : 0 1 2 3 4 5 SEIRwpGuardBandFlag : 1 1 1 1 1 1 SEIRwpProjRegionWidth : 512 512 512 512 512 512 SEIRwpProjRegionHeight : 128 128 128 128 128 128 SEIRwpProjRegionTop : 256 256 256 256 256 256 SEIRwpProjRegionLeft : 0 256 512 768 1024 1280 SEIRwpPackedRegionWidth : 512 512 512 384 384 384 SEIRwpPackedRegionHeight : 128 128 128 192 192 192 SEIRwpPackedRegionTop : 64 64 64 64 64 64 SEIRwpPackedRegionLeft : 32 32 32 32 32 32 SEIRwpLeftGuardBandWidth : 64 64 64 64 64 64 SEIRwpRightGuardBandWidth : 128 128 128 128 128 128 SEIRwpTopGuardBandHeight : 192 192 192 192 192 192 SEIRwpBottomGuardBandHeight : 255 255 255 255 255 255 SEIRwpGuardBandNotUsedForPredFlag : 1 1 1 1 1 1 SEIRwpGuardBandType : 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 0 0 0 0 1 1 1 1 HM-HM-18.0/cfg/sei/rns/000077500000000000000000000000001442026013100143625ustar00rootroot00000000000000HM-HM-18.0/cfg/sei/rns/rns_0.txt000066400000000000000000000042051442026013100161450ustar00rootroot00000000000000num_seis: 2 num_regions: 2 0 10 10 10 20 1 20 20 30 40 payloadType: 142 colour_remap_id: 0 colour_remap_cancel_flag: 0 colour_remap_persistence_flag: 1 colour_remap_video_signal_info_present_flag: 1 colour_remap_full_range_flag: 0 colour_remap_primaries: 9 colour_remap_transfer_function: 16 colour_remap_matrix_coefficients: 9 colour_remap_input_bit_depth: 10 colour_remap_bit_depth: 10 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 64 pre_lut_coded_value[c][i]: 940 pre_lut_target_value[c][i]: 500 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 128 pre_lut_coded_value[c][i]: 960 pre_lut_target_value[c][i]: 896 pre_lut_num_val_minus1[c]: 1 pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 192 pre_lut_coded_value[c][i]: 960 pre_lut_target_value[c][i]: 832 colour_remap_matrix_present_flag: 0 post_lut_num_val_minus1[c]: 1 post_lut_coded_value[c][i]: 64 post_lut_target_value[c][i]: 64 post_lut_coded_value[c][i]: 500 post_lut_target_value[c][i]: 940 post_lut_num_val_minus1[c]: 1 post_lut_coded_value[c][i]: 128 post_lut_target_value[c][i]: 64 post_lut_coded_value[c][i]: 896 post_lut_target_value[c][i]: 960 post_lut_num_val_minus1[c]: 1 post_lut_coded_value[c][i]: 192 post_lut_target_value[c][i]: 64 post_lut_coded_value[c][i]: 832 post_lut_target_value[c][i]: 960 num_regions: 2 3 10 10 30 20 1 20 20 30 40 payloadType: 149 SEICCVCancelFlag : 0 SEICCVPersistenceFlag : 1 SEICCVPrimariesPresent : 1 m_ccvSEIPrimariesX0 : 0.300 m_ccvSEIPrimariesY0 : 0.600 m_ccvSEIPrimariesX1 : 0.150 m_ccvSEIPrimariesY1 : 0.060 m_ccvSEIPrimariesX2 : 0.640 m_ccvSEIPrimariesY2 : 0.330 SEICCVMinLuminanceValuePresent : 1 SEICCVMinLuminanceValue : 0.0 SEICCVMaxLuminanceValuePresent : 1 SEICCVMaxLuminanceValue : 0.1 SEICCVAvgLuminanceValuePresent : 1 SEICCVAvgLuminanceValue : 0.01 HM-HM-18.0/cfg/sei/rns/rns_2.txt000066400000000000000000000020421442026013100161440ustar00rootroot00000000000000num_seis: 3 num_regions: 2 0 10 10 10 20 1 20 20 30 40 payloadType: 140 SEIChromaResamplingHorizontalFilterType: 0 SEIChromaResamplingVerticalFilterType: 2 num_regions: 2 4 10 10 30 20 1 20 20 30 40 payloadType: 149 SEICCVCancelFlag : 0 SEICCVPersistenceFlag : 1 SEICCVPrimariesPresent : 1 m_ccvSEIPrimariesX0 : 0.300 m_ccvSEIPrimariesY0 : 0.600 m_ccvSEIPrimariesX1 : 0.150 m_ccvSEIPrimariesY1 : 0.060 m_ccvSEIPrimariesX2 : 0.640 m_ccvSEIPrimariesY2 : 0.330 SEICCVMinLuminanceValuePresent : 1 SEICCVMinLuminanceValue : 0.0 SEICCVMaxLuminanceValuePresent : 1 SEICCVMaxLuminanceValue : 0.1 SEICCVAvgLuminanceValuePresent : 1 SEICCVAvgLuminanceValue : 0.01 num_regions: 2 5 10 10 10 20 6 20 20 30 40 payloadType: 140 SEIChromaResamplingHorizontalFilterType: 2 SEIChromaResamplingVerticalFilterType: 2 HM-HM-18.0/cfg/sei/shutter_interval_info.cfg000066400000000000000000000007461442026013100206650ustar00rootroot00000000000000#======== Shutter Interval Info SEI message ===================== SEIShutterIntervalEnabled : 1 SEISiiTimeScale : 27000000 SEISiiInputNumUnitsInShutterInterval : 1080000 # should have at least one entry. if only one entry, the value is assigned to sii_num_units_in_shutter_interval, # if multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ] HM-HM-18.0/cfg/sei/shutter_interval_info_fix.cfg000066400000000000000000000006621442026013100215300ustar00rootroot00000000000000#======== Shutter Interval Info SEI message ===================== SEIShutterIntervalEnabled : 1 SEISiiTimeScale : 24000000 SEISiiInputNumUnitsInShutterInterval : 200000 # fixed shutter interval: only one entry, the value is assigned to sii_num_units_in_shutter_interval. # here is one example with frame rate=120fps, encoder derives the actually value based on frame rate. HM-HM-18.0/cfg/sei/shutter_interval_info_mul.cfg000066400000000000000000000007701442026013100215370ustar00rootroot00000000000000#======== Shutter Interval Info SEI message ===================== SEIShutterIntervalEnabled : 1 SEISiiTimeScale : 24000000 SEISiiInputNumUnitsInShutterInterval : 400000 400000 400000 400000 200000 # multiple shutter intervals: multiple entries, the values are set to sub_layer_num_units_in_shutter_interval[ ]. # here is one example with frame rate=120fps, encoder derives the actually values based on picture frame rate. HM-HM-18.0/cfg/sei/sphere_rotation.cfg000066400000000000000000000005331442026013100174470ustar00rootroot00000000000000#======== Sphere Rotation SEI message ===================== SEISphereRotationEnabled : 1 SEISphereRotationCancelFlag : 0 SEISphereRotationPersistenceFlag : 1 SEISphereRotationYaw : -5898240 SEISphereRotationPitch : -5898240 SEISphereRotationRoll : -11796480 HM-HM-18.0/cmake/000077500000000000000000000000001442026013100133215ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/000077500000000000000000000000001442026013100152615ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/000077500000000000000000000000001442026013100160315ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/cmake.py000077500000000000000000000002771442026013100174740ustar00rootroot00000000000000#!/usr/bin/python3 # # cmake.py # import pyhhi.build.common.util import pyhhi.build.app.cmk app = pyhhi.build.app.cmk.CMakeLauncherApp() pyhhi.build.common.util.exec_main_default_try(app) HM-HM-18.0/cmake/CMakeBuild/bin/cmake_docutil.py000077500000000000000000000003221442026013100212060ustar00rootroot00000000000000#!/usr/bin/python3 # # cmake_docutil.py # import pyhhi.build.app.cmkdocapp import pyhhi.build.common.util app = pyhhi.build.app.cmkdocapp.CMakeDocUtilApp() pyhhi.build.common.util.exec_main_default_try(app) HM-HM-18.0/cmake/CMakeBuild/bin/cmakebuild_update.py000077500000000000000000000003261442026013100220510ustar00rootroot00000000000000#!/usr/bin/python3 # # cmakebuild_update.py # import pyhhi.build.app.cmbldup import pyhhi.build.common.util app = pyhhi.build.app.cmbldup.CMakeBuildUpdateApp() pyhhi.build.common.util.exec_main_default_try(app) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/000077500000000000000000000000001442026013100171525ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/__init__.py000077500000000000000000000000001442026013100212540ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/000077500000000000000000000000001442026013100202515ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/__init__.py000077500000000000000000000000001442026013100223530ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/app/000077500000000000000000000000001442026013100210315ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/app/__init__.py000066400000000000000000000000001442026013100231300ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/app/cmbldup.py000077500000000000000000000455021442026013100230420ustar00rootroot00000000000000 from __future__ import print_function import argparse import logging import os import re import subprocess import sys import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver import pyhhi.build.vcsutil as vcsutil from pyhhi.build.common.system import SystemInfo from pyhhi.build.common.error import InvalidInputParameterError class CMakeBuildUpdateAppParams(object): def __init__(self): self.top_dir = None self.update_prepare = True self.cmakebuild_repo = 'git@vigitlab.fe.hhi.de:git/CMakeBuildCore.git' # A CMakeBuild tag of None means latest tag. self.cmakebuild_tag = None class CMakeBuildUpdateApp(object): def __init__(self): self._logger = logging.getLogger(__name__) self._sys_info = SystemInfo() self._prog_name = os.path.basename(sys.argv[0]) self._prog_name_full = os.path.normpath(os.path.abspath(sys.argv[0])) self._list_summary = True self._summary_lines = [] self._git_helper = vcsutil.GitHelper() self._git_executable = self._git_helper.get_git_executable() # List of python modules this script depends on. self._py_mod_list = ['pyhhi.build.app.cmbldup', 'pyhhi.build.vcsutil', 'pyhhi.build.common.cmbldver', 'pyhhi.build.common.error', 'pyhhi.build.common.system', 'pyhhi.build.common.util', 'pyhhi.build.common.ver'] self._usage = """ %(prog)s [options] [top_dir] %(prog)s updates a CMakeBuild Git subtree embedded inside a Git standard workspace. The update procedure requires a clean Git working directory. Unfinished work must be saved somehow; e.g. use git stash .. or anything else. The optional positional argument allows you to update an existing Git workspace out-of-tree. """ self._epilog = """ """ def __call__(self, argv=None): if argv is None: self.main(sys.argv[1:]) else: self.main(argv) def main(self, argv): params = self._parse_command_line(argv) self.cmakebuild_update(params) def cmakebuild_update(self, params): initial_work_dir = os.getcwd() # (Re)create GitHelper in case the log level has been changed. self._git_helper = vcsutil.GitHelper() params = self._check_params(params) if params.top_dir is None: params.top_dir = util.get_top_dir() self._summary_lines = [] if params.update_prepare: print("{}: preparing CMakeBuild update ...".format(self._prog_name)) cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is None: print("{}: no existing CMakeBuild version found.".format(params.top_dir)) if not self._is_workspace_clean(params.top_dir): return if params.cmakebuild_tag is None: cmakebuild_tag = self._git_helper.get_latest_cmakebuild_tag(params.cmakebuild_repo) if cmakebuild_version_current and (ver.version_compare(cmakebuild_version_current, ver.version_tuple_from_str(cmakebuild_tag)) == 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return else: # Validate CMakeBuild tag cmakebuild_tags = self._git_helper.get_remote_tags(params.cmakebuild_repo) if params.cmakebuild_tag not in cmakebuild_tags: raise InvalidInputParameterError("requested tag {0} does not exists in {1}.".format(params.cmakebuild_tag, params.cmakebuild_repo)) cmakebuild_tag = params.cmakebuild_tag if cmakebuild_version_current and (ver.version_compare(ver.version_tuple_from_str(cmakebuild_tag), cmakebuild_version_current) <= 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return install_dir = os.path.join(params.top_dir, 'build', 'cmakebuild_update') self._install_self(install_dir) update_script = os.path.join(install_dir, self._prog_name) # Prepare execv argument vector to call self with different arguments using the current python executable. if self._sys_info.is_windows(): child_args = [self._sys_info.get_short_path(self._sys_info.get_python_executable())] else: child_args = [self._sys_info.get_python_executable()] child_args.extend([update_script, '--update']) if cmakebuild_tag: child_args.extend(['-t', cmakebuild_tag]) if params.cmakebuild_repo: child_args.extend(['--cmakebuild-repo', params.cmakebuild_repo]) # Add currrent log option to child_args[] to propagate the current log option to the child process. log_level = self._logger.getEffectiveLevel() log_level_str = None if log_level == logging.DEBUG: log_level_str = 'debug' elif log_level == logging.INFO: log_level_str = 'info' elif log_level == logging.WARNING: log_level_str = 'warning' elif log_level == logging.ERROR: log_level_str = 'error' elif log_level == logging.CRITICAL: log_level_str = 'critical' if log_level_str is not None: child_args.append('--log={}'.format(log_level_str)) child_args.append(params.top_dir) os.chdir(params.top_dir) if self._sys_info.is_windows(): # Unfortunately, there are issues with os.execv() on Windows and therefore a subprocess call is used instead. util.subproc_check_call_flushed(child_args) else: # execv() is preferred as the child is likely to remove python files just being executed # by the current python process. os.execv(child_args[0], child_args) else: try: print("{}: updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) os.chdir(params.top_dir) if not self._is_workspace_clean(): return self._append_item_to_summary("Git workspace:", params.top_dir) if self._list_summary: cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is not None: self._append_item_to_summary("Current CMakeBuild version:", "{}-{:d}".format(ver.version_tuple_to_str(cmakebuild_version_current[:3]), cmakebuild_version_current[-1])) self._append_item_to_summary("New CMakeBuild version:", params.cmakebuild_tag) # Inventory of CMakeBuild to remember existing directories to be removed later on. (git_cmakebuild_dirs, cmakebuild_dirs) = self._get_git_cmakebuild_dirs(params.top_dir) if params.cmakebuild_tag in git_cmakebuild_dirs: git_cmakebuild_dirs.remove(params.cmakebuild_tag) if params.cmakebuild_tag in cmakebuild_dirs: cmakebuild_dirs.remove(params.cmakebuild_tag) # print("found existing Git CMakeBuild subdirs:", git_cmakebuild_dirs) # print("found existing CMakeBuild subdirs:", cmakebuild_dirs) # Add new CMakeBuild subtree self._add_cmakebuild_to_git_repo(params.cmakebuild_tag, params.cmakebuild_repo) # Update .svnimportprops in case is does exist. svnimportprops_file = os.path.join(params.top_dir, '.svnimportprops') svnimportprops_modified = self._update_svnimportprops(svnimportprops_file, params.cmakebuild_tag) for dname in git_cmakebuild_dirs: git_argv = [self._git_executable, 'rm', '-r', os.path.join('CMakeBuild', dname)] util.subproc_check_call_flushed(git_argv) if svnimportprops_modified or git_cmakebuild_dirs: # Need a git commit if '.svnimportprops' has been updated or git rm -r has been launched. git_comment = [] if git_cmakebuild_dirs: git_comment.append("rm -r CMakeBuild/{}".format(','.join(git_cmakebuild_dirs))) if svnimportprops_modified: git_comment.append("modifying {}".format('.svnimportprops')) git_argv = [self._git_executable, 'commit', '-am', '{}: {}'.format(self._prog_name, ', '.join(git_comment))] util.subproc_check_call_flushed(git_argv) # Check again to get rid of any python cache files cmakebuild_dirs.extend(git_cmakebuild_dirs) for dname in cmakebuild_dirs: dname_path = os.path.join(params.top_dir, 'CMakeBuild', dname) if os.path.exists(dname_path): util.rmtree(dname_path) print("{}: finished updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) if self._list_summary: print("\n{0:^80}".format("Summary")) print("{0:^80}".format("=======")) for line in self._summary_lines: print(line) finally: pass os.chdir(initial_work_dir) def _parse_command_line(self, argv): params = CMakeBuildUpdateAppParams() parser = argparse.ArgumentParser(usage=self._usage, epilog=self._epilog, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("top_dir", action="store", nargs='?', default=None, help="specifies a Git workspace to work on. By default the scripts installation path will be used to deduce the workspace.") util.app_args_add_log_level(parser) parser.add_argument("-t", "--tag", action="store", dest="cmakebuild_tag", metavar="TAG", help="specifies a CMakeBuild tag to be used. If omitted the latest release tag will be used.") parser.add_argument("--cmakebuild-repo", action="store", dest="cmakebuild_repo", metavar="REPO", default=params.cmakebuild_repo, help="specifies an alternative CMakeBuild repository overriding %(default)s." ) parser.add_argument("--update", action="store_true", dest="update", default=False, help="execute cmakebuild update, internal option reserved for the os.execv() machinery.") args = parser.parse_args(argv) # configure the python logger util.app_configure_logging(args.log_level) if args.top_dir: params.top_dir = os.path.normpath(os.path.abspath(args.top_dir)) if args.cmakebuild_tag: params.cmakebuild_tag = args.cmakebuild_tag if args.cmakebuild_repo: params.cmakebuild_repo = args.cmakebuild_repo if args.update: params.update_prepare = False return params def _check_params(self, params): params.cmakebuild_repo = self._check_git_url(params.cmakebuild_repo) if params.top_dir: if not os.path.exists(params.top_dir): raise InvalidInputParameterError("Git workspace {} does not exist.".format(params.top_dir)) if not os.path.exists(os.path.join(params.top_dir, '.git')): raise InvalidInputParameterError("Workspace {} does not seem to be a Git workspace.".format(params.top_dir)) return params def _check_git_url(self, git_url): vcs_url = vcsutil.VcsUrl(git_url) proto = vcs_url.get_protocol() if proto in ['ssh', 'https']: # Normalize a remote Git URL to end with .git even if specified without the extension. res_path = vcs_url.get_resource_path() if not res_path.endswith('.git'): vcs_url.set_resource_path("{}.git".format(res_path)) else: raise InvalidInputParameterError("Git URL {0} is not supported yet.".format(git_url)) # Normalize all URLs. git_url = str(vcs_url) self._logger.debug("returning url={0}".format(git_url)) return git_url def _install_self(self, install_dir): script_installer = self._create_script_installer() # print("py_mod_list:", self._py_mod_list) script_installer.install_script(install_dir, self._prog_name_full, self._py_mod_list) def _create_script_installer(self): import pyhhi.build.common.bldtools script_installer = pyhhi.build.common.bldtools.BuildScriptInstaller(verbose=True) return script_installer def _get_current_cmakebuild_version(self, top_dir): assert os.path.exists(top_dir) cmakebuild_top_dir = os.path.join(top_dir, 'CMakeBuild') if not os.path.exists(cmakebuild_top_dir): return None re_version_dir = re.compile(r'^\d+[0-9.]+-\d+$') version_list = [] for fname in os.listdir(cmakebuild_top_dir): if os.path.isdir(os.path.join(cmakebuild_top_dir, fname)): if re_version_dir.match(fname) and os.path.exists(os.path.join(cmakebuild_top_dir, fname, 'CMakeBuild', 'bin', 'cmake.py')): version_list.append(ver.version_tuple_from_str(fname)) if not version_list: return None if len(version_list) > 1: raise InvalidInputParameterError("Workspace {} contains multiple CMakeBuild versions, please update manually.".format(top_dir)) self._logger.debug("found CMakeBuild {} in {}".format(ver.version_tuple_to_str(version_list[0]), top_dir)) return version_list[0] def _get_git_cmakebuild_dirs(self, top_dir): assert os.path.exists(top_dir) cmakebuild_top_dir = os.path.join(top_dir, 'CMakeBuild') if not os.path.exists(cmakebuild_top_dir): return [] re_version_dir = re.compile(r'^\d+[0-9.]+-\d+$') git_cmakebuild_version_dirs = [] cmakebuild_version_dirs = [] for fname in os.listdir(cmakebuild_top_dir): if os.path.isdir(os.path.join(cmakebuild_top_dir, fname)): if re_version_dir.match(fname): git_argv = [self._git_executable, 'ls-files', os.path.join('CMakeBuild', fname)] retv = subprocess.check_output(git_argv, universal_newlines=True) retv = retv.lstrip().rstrip() if retv != '': git_cmakebuild_version_dirs.append(fname) else: cmakebuild_version_dirs.append(fname) return git_cmakebuild_version_dirs, cmakebuild_version_dirs def _is_workspace_clean(self, top_dir=None): if top_dir: initial_work_dir = os.getcwd() os.chdir(top_dir) else: initial_work_dir = None top_dir = os.getcwd() git_argv = [self._git_executable, 'status', '-b', '--porcelain'] retv = subprocess.check_output(git_argv, universal_newlines=True) retv = retv.lstrip().rstrip() status_lines = retv.splitlines() if status_lines[0].startswith('## HEAD (no branch)'): raise InvalidInputParameterError("Git workspace {} has detached HEAD, not upgradable.".format(top_dir)) if len(status_lines) > 1: raise InvalidInputParameterError("Git workspace {} is not clean, please check.".format(top_dir)) if initial_work_dir: os.chdir(initial_work_dir) return True def _add_cmakebuild_to_git_repo(self, cmakebuild_tag, cmakebuild_repo): self._logger.info("using CMakeBuild tag {} as subtree.".format(cmakebuild_tag)) # # Extra annoying step to convince git subtree the working dir is clean # git_argv = [self._git_executable, 'checkout'] self._git_helper.trace_git_command(git_argv) util.subproc_check_call_flushed(git_argv) subtree_prefix = "CMakeBuild/{0}".format(cmakebuild_tag) git_argv = [self._git_executable, 'subtree', 'add', '-P', subtree_prefix, '--squash', '-m', "{0}: creates subtree -P {1} tag={2}".format(self._prog_name, subtree_prefix, cmakebuild_tag), cmakebuild_repo, cmakebuild_tag] util.subproc_check_call_flushed(git_argv) def _update_svnimportprops(self, svnimportprops_file, cmakebuild_tag, svnimportprops_file_new=None): svnimportprops_modified = False if not os.path.exists(svnimportprops_file): return svnimportprops_modified svnprop_file_parser = vcsutil.SvnPropFileParser() svnprops = svnprop_file_parser.parse_property_file(svnimportprops_file) if not svnprops.has_property('svn:externals'): svnimportprops_modified = True svnprops.add_property('svn:externals', ["/svn/svn_CMakeBuild/tags/{}/CMakeBuild CMakeBuild".format(cmakebuild_tag)]) else: svnprop_externals = svnprops.get_property('svn:externals') re_external_cmakebuild = re.compile(r'^/svn/svn_CMakeBuild/tags/([^/]+)/CMakeBuild\s+') svnprop_externals_new = [] for line in svnprop_externals: if (line == '') or line.isspace(): continue self._logger.debug("processing line {}".format(line)) re_match = re_external_cmakebuild.match(line) if re_match: cmakebuild_tag_existing = re_match.group(1) self._logger.debug("{}: found CMakeBuild tag {}".format(svnimportprops_file, cmakebuild_tag_existing)) if cmakebuild_tag_existing != cmakebuild_tag: svnimportprops_modified = True svnprop_externals_new.append("/svn/svn_CMakeBuild/tags/{}/CMakeBuild CMakeBuild".format(cmakebuild_tag)) else: svnprop_externals_new.append(line) else: svnprop_externals_new.append(line) if svnimportprops_modified: svnprops.update_property('svn:externals', svnprop_externals_new) if svnimportprops_modified: self._logger.debug("{}: updating changed svn:externals".format(svnimportprops_file)) if svnimportprops_file_new is None: svnimportprops_file_new = svnimportprops_file with open(svnimportprops_file_new, 'w') as f: svnprops_str = str(svnprops) f.write(svnprops_str) return svnimportprops_modified def _append_item_to_summary(self, item, value): self._summary_lines.append("{0:<30} {1}".format(item, value)) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/app/cmk.py000077500000000000000000000450501442026013100221640ustar00rootroot00000000000000 from __future__ import print_function import argparse import logging import os import re import shutil import sys import pyhhi.build.common.system as system import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver import pyhhi.build.common.bldtools as bldtools import pyhhi.build.cmksupp as cmksupp from pyhhi.build.common.bldtools import BuildScriptInstaller from pyhhi.build.common.error import InvalidCommandLineArgumentError class CMakeLauncherApp(object): def __init__(self): self._logger = logging.getLogger(__name__) self._sys_info = system.SystemInfo() self._cmake_launcher = None self._dict_generator_choice = {'linux': ['umake', 'ninja'], 'macosx': ['xcode', 'umake', 'ninja'], 'windows': ['vs16', 'vs15', 'vs14', 'vs12', 'vs11', 'vs10', 'umake', 'mgwmake', 'ninja']} self._top_dir = None self._cmake_mod_list = ['pyhhi.build.app.cmk', 'pyhhi.build.cmkfnd', 'pyhhi.build.cmksupp', 'pyhhi.build.common.bldtools', 'pyhhi.build.common.cmbldver', 'pyhhi.build.common.error', 'pyhhi.build.common.system', 'pyhhi.build.common.util', 'pyhhi.build.common.ver'] def __call__(self): self.main(sys.argv[1:]) def main(self, argv): # self._print_env() (params, cmake_argv) = self._parse_command_line(argv) if params.install_dir: top_dir = util.get_top_dir() os.chdir(top_dir) script_dir = util.get_script_dir() # print("sys.path: ", sys.path) script_installer = BuildScriptInstaller(verbose=True) script_installer.install_script(params.install_dir, os.path.join(script_dir, 'cmake.py'), self._cmake_mod_list) elif params.py_cache_dirs: for dname in params.py_cache_dirs: if not os.path.exists(dname): continue if not os.path.isdir(dname): continue self._remove_pycache(dname) else: # Apply additional checks on params. self._check_params(params) if self._sys_info.is_linux() or self._sys_info.is_macosx(): self._remove_make_env_vars() # Delayed construction to get the current log level at construction time of CMakeLauncher. self._cmake_launcher = cmksupp.CMakeLauncher() self._cmake_launcher.launch(params, cmake_argv) def _check_params(self, params): pass def _print_env(self): env_var_list = list(os.environ.keys()) env_var_list.sort() for env_var in env_var_list: print(env_var, os.environ[env_var]) # print(env_var) # if env_var.startswith('MAKE') or (env_var == 'MFLAGS'): # print(env_var) # sys.exit(0) def _remove_make_env_vars(self): make_env_vars = [] for env_var in os.environ.keys(): if env_var.startswith('MAKE') or (env_var == 'MFLAGS'): make_env_vars.append(env_var) for env_var in make_env_vars: self._logger.debug("deleting environment variable: %s", env_var) del os.environ[env_var] def _parse_command_line(self, argv): _usage = """ %(prog)s [options] [variant=debug,release,relwithdebinfo,minsizerel] [link=static,shared] [toolset=] [address-model=32] %(prog)s is a script front end to cmake to simplify its usage on Linux, Windows, MacOSX using cmake's generators "Unix Makefiles", "Ninja", "Xcode" and "Visual Studio 16 - Visual Studio 10" and its compilers. arguments: variant: debug if not specified link: static if not specified toolset: default c++ compiler if not specified examples/windows: msvc-19.1x, msvc-19.0, msvc-18.0, msvc-17.0, msvc-16.0, intel, gcc examples/linux: gcc-4.9, gcc-5, gcc-6, clang, intel address-model=32: windows: builds 32 bit binaries instead of 64 bit binaries """ _epilog = """ usage examples: # debug build, create the build tree if it does not exist. %(prog)s -b # release build, create the build tree if it does not exist. %(prog)s -b variant=release # release build using shared libraries, create the build tree if it does not exist. %(prog)s -b variant=release link=shared # create a build tree without building anything %(prog)s # create a build tree specifying a cmake cache entry without building anything %(prog)s -DENABLE_SOMETHING=1 """ parser = argparse.ArgumentParser(usage=_usage, epilog=_epilog, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--cmake-bin-dir", action="store", dest="cmk_bin_dir", help="specify a directory to search for CMake overriding the default CMake search path.") parser.add_argument("-g", "-G", action="store", dest="generator", choices=self._dict_generator_choice[self._sys_info.get_platform()], help="""specify a cmake generator the script has special support for. Supported generators: ninja, umake, mgwmake, vs16, vs15, vs14, vs12, vs11, vs10, xcode. The choices accepted are platform and installation dependent. The environment variable DEFAULT_CMAKE_GENERATOR may be used to override the default value.""") parser.add_argument("-D", action="append", dest="cache_entries", help="specify a cmake cache entry. The option will be ignored if a build tree already exists.") parser.add_argument("-W", action="append", dest="warning_flags", help="specify a cmake warning flag.") parser.add_argument("-b", action="store_true", dest="build", default=False, help="""invokes cmake --build to build the default debug configuration unless overridden by additional arguments. If a build tree does not exist, it will be created.""") parser.add_argument("-j", action="store", dest="build_jobs", type=int, nargs='?', default=1, const=str(self._get_optimal_number_cmake_jobs()), help="""specify the number of parallel build jobs. If you omit the numeric argument, cmake --build ... will be invoked with -j%(const)s.""") parser.add_argument("--target", action="store", dest="build_target", help="specify a build target overriding the default target.") parser.add_argument("--clean-first", action="store_true", dest="clean_first", default=False, help="build target clean first, then build the active target.") parser.add_argument("--verbosity", action="store", dest="build_verbosity", choices=['cmake', 'quiet', 'minimal', 'normal', 'detailed', 'diagnostic'], default='minimal', help="""specify (ms)build verbosity level [default: %(default)s]. The choice 'cmake' requires cmake 3.14.x or higher to increase build verbosity for Visual Studio and other generators.""") util.app_args_add_log_level(parser) g = parser.add_argument_group("advanced options") g.add_argument("-i", action="store", dest="install_dir", nargs='?', const=os.path.join(self._sys_info.get_home_dir(native=True), 'bin'), help="install this script and exit. The default destination directory is %(const)s.") g.add_argument("--py-cache-clean", action="store", dest="py_cache_dirs", nargs='+', help="search for Python cache files in one or more directory trees, remove them and exit. This special option is intended " "for cross-platform Makefiles to clean up the source tree as python cache files are stored next to the source and " "not in the build tree.") # -j may be followed by a non-numeric argument which the parser is not able to handle. if '-j' in argv: i = argv.index('-j') # If the next argument is all numeric, attach it directly. In all other cases use the optimal number of parallel jobs. if i < (len(argv) - 1): if re.match(r'\d+$', argv[i + 1]): argv_parsed = argv else: # make a copy -> don't want to modify sys.argv. argv_parsed = argv[:] argv_parsed[i] = '-j' + str(self._get_optimal_number_cmake_jobs()) else: # make a copy -> don't want to modify sys.argv. argv_parsed = argv[:] argv_parsed[i] = '-j' + str(self._get_optimal_number_cmake_jobs()) else: argv_parsed = argv (cmake_py_options, args_left) = parser.parse_known_args(argv_parsed) # configure the python logger asap util.app_configure_logging(cmake_py_options.log_level) launcher_params = cmksupp.CMakeLauncherParams() cmake_args = [] if cmake_py_options.install_dir: # print("-i found, install dir", cmake_py_options.install_dir) if os.path.isabs(cmake_py_options.install_dir): launcher_params.install_dir = cmake_py_options.install_dir else: launcher_params.install_dir = os.path.abspath(cmake_py_options.install_dir) elif cmake_py_options.py_cache_dirs: launcher_params.py_cache_dirs = [] for dname in cmake_py_options.py_cache_dirs: launcher_params.py_cache_dirs.append(os.path.normpath(os.path.abspath(dname))) self._top_dir = os.getcwd() if cmake_py_options.install_dir or launcher_params.py_cache_dirs: return launcher_params, cmake_args # if args_left: # print("cmake args", args_left) # Assign cmake.py options to attributes of CMakeLauncherParams. launcher_params.cmk_bin_dir = cmake_py_options.cmk_bin_dir launcher_params.cmk_build = cmake_py_options.build launcher_params.cmk_build_jobs = cmake_py_options.build_jobs launcher_params.clean_first = cmake_py_options.clean_first launcher_params.cmk_build_target = cmake_py_options.build_target launcher_params.cmk_build_verbosity = cmake_py_options.build_verbosity launcher_params.cmk_generator_alias = cmake_py_options.generator if cmake_py_options.cache_entries: launcher_params.cmk_cache_entries = ['-D' + x for x in cmake_py_options.cache_entries] if cmake_py_options.warning_flags: launcher_params.cmk_warning_flags = ['-W' + x for x in cmake_py_options.warning_flags] re_cmake_py_arg = re.compile(r'(toolset|variant|link|address-model)=(\S+)') for arg in args_left: # print("processing argument " + arg) re_match = re_cmake_py_arg.match(arg) if re_match: arg_key = re_match.group(1) arg_value = re_match.group(2) if arg_key == 'toolset': if arg_value.endswith('.cmake'): # A toolset=.cmake expression is supposed to be a toolchain file to enable # some kind of cross compilation. if not os.path.exists(arg_value): raise InvalidCommandLineArgumentError("toolchain file={} does not exist.".format(arg_value)) launcher_params.toolset_str = os.path.abspath(arg_value) else: launcher_params.toolset_str = self._normalize_toolset_spec(arg_value) elif arg_key == 'variant': build_configs = arg_value.split(',') for cfg in build_configs: if cfg not in ['release', 'debug', 'relwithdebinfo', 'minsizerel']: raise InvalidCommandLineArgumentError("argument {} is not understood.".format(arg)) launcher_params.build_configs = build_configs elif arg_key == 'link': link_variants = arg_value.split(',') for lnk in link_variants: if lnk not in ['static', 'shared']: raise InvalidCommandLineArgumentError("argument {} is not understood.".format(arg)) launcher_params.link_variants = link_variants elif arg_key == 'address-model': if arg_value == '32': launcher_params.target_arch = 'x86' elif arg_value == '64': launcher_params.target_arch = 'x86_64' else: raise InvalidCommandLineArgumentError("argument {} is not understood.".format(arg)) else: raise Exception("argument {} is not understood.".format(arg)) continue if arg == '--': # Semantics seems to be tricky and I haven't seen a convincing use case yet. # In configuration mode all unknown arguments are passed verbatim to cmake and in build mode # all unknown arguments are really build tool arguments and are passed verbatim to the build tool. raise InvalidCommandLineArgumentError("argument '--' encountered, this is not yet supported, please contact the maintainer.") # all other arguments are passed on to cmake verbatim. cmake_args.append(arg) return launcher_params, cmake_args def _normalize_toolset_spec(self, toolset_spec): toolset_spec_norm = toolset_spec if self._sys_info.is_linux(): if toolset_spec.find('-g++') >= 0: # x86_64-w64-mingw32-g++-posix -> normalized to x86_64-w64-mingw32-gcc-posix toolset_spec_norm = toolset_spec.replace('-g++', '-gcc') if toolset_spec_norm.find('-gcc') >= 0: # looks like a cross compiler specification which requires a toolchain file matching the toolset spec and the linux system. toolset_spec_norm = self._find_toolchain_file(toolset_spec_norm) elif self._sys_info.is_windows(): if toolset_spec.startswith('msvc-'): msvc_registry = bldtools.MsvcRegistry() if toolset_spec == 'msvc-19.2x': if msvc_registry.is_version_installed((14, 2)): cl_version = msvc_registry.get_compiler_version((14, 2)) toolset_spec_norm = "msvc-{0:d}.{1:d}".format(cl_version[0], cl_version[1]) else: raise InvalidCommandLineArgumentError("toolset={} not available.".format(toolset_spec)) elif toolset_spec == 'msvc-19.1x': if msvc_registry.is_version_installed((14, 1)): cl_version = msvc_registry.get_compiler_version((14, 1)) toolset_spec_norm = "msvc-{0:d}.{1:d}".format(cl_version[0], cl_version[1]) else: raise InvalidCommandLineArgumentError("toolset={} not available.".format(toolset_spec)) else: # msvc-19.00 -> normalized to 19.0 re_match = re.match(r'msvc-(\d+)\.(\d+)', toolset_spec) if re_match: minor_version = int(re_match.group(2)) toolset_spec_norm = "msvc-{0}.{1:d}".format(re_match.group(1), minor_version) elif self._sys_info.is_macosx(): pass else: # unsupported platform -> contact maintainer assert False return toolset_spec_norm def _find_toolchain_file(self, toolset_spec): toolchain_file = None toolchains_dir = self._find_toolchains_dir() if toolchains_dir is not None: if self._sys_info.is_linux(): toolchain_file_suffix = '-' + self._sys_info.get_os_distro_short() if self._sys_info.get_os_distro_short() == 'ubuntu': os_version_str = ver.ubuntu_version_tuple_to_str(self._sys_info.get_os_version()) else: os_version_str = self._sys_info.get_os_version() toolchain_file_suffix += os_version_str.replace('.', '') + '.cmake' if os.path.exists(os.path.join(toolchains_dir, toolset_spec + toolchain_file_suffix)): toolchain_file = os.path.join(toolchains_dir, toolset_spec + toolchain_file_suffix) if toolchain_file is None: msg = "toolset=" + toolset_spec + " cannot be mapped to a default toolchain file automatically. Please use a toolchain file or " msg += "contact technical support." raise Exception(msg) return toolchain_file def _find_toolchains_dir(self): toolchains_dir = os.path.join(util.get_script_dir(), '..', 'cmake', 'toolchains') if not os.path.exists(toolchains_dir): self._logger.warning("toolchains dir {} does not exist.".format(toolchains_dir)) return None toolchains_dir = os.path.normpath(toolchains_dir) return toolchains_dir def _get_workspace_folder(self): assert self._top_dir is not None return self._top_dir def _get_optimal_number_cmake_jobs(self): """Returns the optimal number of cmake jobs.""" cmake_jobs = self._sys_info.get_number_processors() if 'CMAKE_MAX_JOBS' in os.environ: cmake_max_jobs = int(os.environ['CMAKE_MAX_JOBS'], 10) if cmake_jobs > cmake_max_jobs: cmake_jobs = cmake_max_jobs assert cmake_jobs >= 1 return cmake_jobs def _remove_pycache(self, py_dir_root): os.chdir(py_dir_root) re_pyc_file = re.compile(r'.+\.pyc$', re.IGNORECASE) for root, dirs, files in os.walk(py_dir_root): if '__pycache__' in dirs: self._logger.info("rm -rf {0}".format(os.path.join(root,'__pycache__'))) shutil.rmtree(os.path.join(root, '__pycache__')) dirs.remove('__pycache__') for fname in files: if re_pyc_file.match(fname): self._logger.info("rm {0}".format(os.path.join(root, fname))) os.remove(os.path.join(root, fname)) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/app/cmkdocapp.py000077500000000000000000000072511442026013100233540ustar00rootroot00000000000000 from __future__ import print_function import argparse import logging import os.path import sys import pyhhi.build.common.util as util import pyhhi.build.cmkdoc as cmkdoc from pyhhi.build.common.error import InvalidCommandLineArgumentError, InvalidInputParameterError class CMakeDocUtilApp(object): def __init__(self): self._logger = logging.getLogger(__name__) def __call__(self): self.main(sys.argv[1:]) def main(self, argv): params = self._parse_command_line(argv) self.update_cmake_manual_docs(params) def update_cmake_manual_docs(self, params): self._check_params(params) cmkdocutil = cmkdoc.CMakeManualRstUtil(dry_run=params.dry_run) if params.update_action == 'add': cmkdocutil.add_extension_modules(params.rst_module_filenm, params.extension_module_names, output_rst_filenm=params.output_rst_filenm, section_title=params.extension_section_title) elif params.update_action == 'remove': cmkdocutil.remove_extension_module_section(params.rst_module_filenm, output_rst_filenm=params.output_rst_filenm, section_title=params.extension_section_title) elif params.update_action == 'remove_all': cmkdocutil.remove_all_extension_modules(params.rst_module_filenm, output_rst_filenm=params.output_rst_filenm) else: assert False def _check_params(self, params): assert params.rst_module_filenm is not None if not os.path.exists(params.rst_module_filenm): raise InvalidInputParameterError("CMake doc module file {} does not exist.".format(params.rst_module_filenm)) def _parse_command_line(self, argv): params = cmkdoc.CMakeRstUtilParams() parser = argparse.ArgumentParser() parser.add_argument("input", action="store", help="specifies the CMake RST module file to be updated.") parser.add_argument("-m", action="append", dest="module_names", help="specifies an extension module name, the option must be repeated for each extension module.") parser.add_argument("-R", action="store_true", dest="remove_all", default=False, help="remove all non-standard module sections.") parser.add_argument("-r", action="store_true", dest="remove", default=False, help="remove a single non-standard module section.") parser.add_argument("-o", action="store", dest="output_rst_filenm") parser.add_argument("-s", action="store", dest="section_title", default=params.extension_section_title, help="specifies the section to be updated [default: %(default)s]") parser.add_argument("--dry-run", action="store_true", dest="dry_run", default=False) util.app_args_add_log_level(parser) args = parser.parse_args(argv) # configure the python logger asap util.app_configure_logging(args.log_level) params.dry_run = args.dry_run params.rst_module_filenm = os.path.abspath(args.input) if args.module_names: params.update_action = 'add' params.extension_module_names = args.module_names elif args.remove_all: params.update_action = 'remove_all' elif args.remove: params.update_action = 'remove' else: raise InvalidCommandLineArgumentError("no update action specified, use -m, -R or -r.") if args.section_title: params.extension_section_title = args.section_title if args.output_rst_filenm: params.output_rst_filenm = os.path.abspath(args.output_rst_filenm) return params HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/cmkdoc.py000077500000000000000000000457711442026013100221040ustar00rootroot00000000000000 from __future__ import print_function import logging import re import os from pyhhi.build.common.error import InvalidInputParameterError class CMakeRstUtilParams(object): def __init__(self): self.dry_run = False self.rst_module_filenm = None self.update_action = 'add' self.extension_module_names = [] self.extension_section_title = "Extension Modules" self.output_rst_filenm = None class RstModuleSection(object): def __init__(self): self.section_title = None self.section_title_marker_line = None self.section_header = [] self.section_content = [] class CMakeManualRstUtil(object): def __init__(self, dry_run=False): self._logger = logging.getLogger(__name__) self._dry_run = dry_run self._section_title_cmake_modules_orig = "All Modules" self._section_title_cmake_modules = "Standard Modules" self._reserved_section_titles = [self._section_title_cmake_modules, self._section_title_cmake_modules_orig, "Legacy CPack Modules"] self._section_title_marker = '=' self._is_cmake_source_tree = False # Location of .rst self._cmake_help_module_dir = None # Automatic removal of cmake module wrapper files. self._autoremove = True self._re_section_content = re.compile(r'\s+/module/([a-zA-Z0-9_-]+)\s*$') def is_cmake_source_tree(self): return self._is_cmake_source_tree def add_extension_modules(self, rst_module_filenm, extension_module_names, section_title="Extension Modules", output_rst_filenm=None): if not os.path.exists(rst_module_filenm): raise InvalidInputParameterError("CMake RST module file {} does not exist.".format(rst_module_filenm)) if output_rst_filenm is None: # in-place replacement output_rst_filenm = rst_module_filenm # Empty sections are not permitted, use one of the remove_xxx() methods to get rid of a section. assert extension_module_names self._detect_cmake_source_tree(rst_module_filenm) self._check_section_title(section_title) (module_file_header, section_list) = self._parse_rst_module_file(rst_module_filenm) if len(section_list) > 0: # CMake's original module file has one or more sections. All extension sections are inserted in front of # section titled "All Modules" or "Standard Modules". The latter title is used after the first extension section has been inserted. # Get cmake module names cmake_module_names_set = self._get_cmake_module_names(section_list) # Extension module names must not replace existing cmake module names extension_module_names_set = set(extension_module_names) if not cmake_module_names_set.isdisjoint(extension_module_names_set): conflicting_names = cmake_module_names_set.intersection(extension_module_names_set) msg = "CMake builtin module names cannot be part of an extension section.\n" msg += "Please check the extension module names: " + " ".join(conflicting_names) raise Exception(msg) else: # Looks like a corrupted cmake-modules.7.rst assert False # Get a list of RST extension module wrapper files belonging to section "section_title". existing_extension_module_names = self._get_extension_module_names(section_list, section_title) if existing_extension_module_names: self._logger.debug('existing extensions: %s', ' '.join(existing_extension_module_names)) modified = self._update_section(section_list, section_title, extension_module_names) if modified: # print("new content lines:") # self._dump_section_list(section_list[0:-1]) # Change title of the CMake module section from "All Modules" to "Standard Modules". for section in section_list: if section.section_title == self._section_title_cmake_modules_orig: section.section_title = self._section_title_cmake_modules section.section_title_marker_line = '{0:=>{width}}'.format(self._section_title_marker, width=len(section.section_title)) break section_list = self._sort_section_list(section_list) # Save top-level RST module file self._save_rst_module_file(output_rst_filenm, module_file_header, section_list) # Remove RST extension module wrapper files not belonging to this section anymore. outdated_extension_module_names = [] for mod_nm in existing_extension_module_names: if mod_nm not in extension_module_names: outdated_extension_module_names.append(mod_nm) if outdated_extension_module_names: self._logger.debug('outdated extensions: %s', ' '.join(outdated_extension_module_names)) # Remove outdated RST extension module wrapper files. self._remove_rst_extension_module_files(outdated_extension_module_names) def remove_extension_module_section(self, rst_module_filenm, section_title="Extension Modules", output_rst_filenm=None): if not os.path.exists(rst_module_filenm): raise Exception("CMake RST module file " + rst_module_filenm + " does not exist.") if output_rst_filenm is None: output_rst_filenm = rst_module_filenm self._detect_cmake_source_tree(rst_module_filenm) self._check_section_title(section_title) (module_file_header, section_list) = self._parse_rst_module_file(rst_module_filenm) assert len(section_list) > 0 # Get a list of RST extension module wrapper files belonging to section "section_title". existing_extension_module_names = self._get_extension_module_names(section_list, section_title) if existing_extension_module_names: self._logger.debug('existing extensions: %s', ' '.join(existing_extension_module_names)) modified = False new_section_list = [] for sect in section_list: if section_title == sect.section_title: modified = True else: new_section_list.append(sect) assert len(new_section_list) > 0 sect = new_section_list[0] if sect.section_title == self._section_title_cmake_modules: modified = True # Recover the original section title sect.section_title = self._section_title_cmake_modules_orig sect.section_title_marker_line = '{0:=>{width}}'.format(self._section_title_marker, width=len(sect.section_title)) if modified: # Save top-level RST module file self._save_rst_module_file(output_rst_filenm, module_file_header, new_section_list) # Remove RST extension module wrapper files belonging to the section just removed. self._remove_rst_extension_module_files(existing_extension_module_names) def remove_all_extension_modules(self, rst_module_filenm, output_rst_filenm=None): if not os.path.exists(rst_module_filenm): raise Exception("CMake RST module file " + rst_module_filenm + " does not exist.") if output_rst_filenm is None: output_rst_filenm = rst_module_filenm self._detect_cmake_source_tree(rst_module_filenm) (module_file_header, section_list) = self._parse_rst_module_file(rst_module_filenm) existing_extension_module_names = self._get_extension_module_names(section_list) if existing_extension_module_names: self._logger.debug('existing extensions: %s', ' '.join(existing_extension_module_names)) modified = False while section_list: sect = section_list[0] if sect.section_title == self._section_title_cmake_modules: # Found first original section modified = True sect.section_title = self._section_title_cmake_modules_orig sect.section_title_marker_line = '{0:=>{width}}'.format(self._section_title_marker, width=len(sect.section_title)) break elif sect.section_title == self._section_title_cmake_modules_orig: # Found first original section break else: modified = True section_list.pop(0) assert len(section_list) > 0 if modified: # Save top-level RST module file self._save_rst_module_file(output_rst_filenm, module_file_header, section_list) # Remove all RST extension module wrapper files self._remove_rst_extension_module_files(existing_extension_module_names) def _detect_cmake_source_tree(self, rst_module_filenm): rst_manual_dir = os.path.dirname(rst_module_filenm) rst_module_dir = os.path.join(rst_manual_dir, '..', 'module') if (os.path.basename(rst_manual_dir) == 'manual') and (os.path.exists(rst_module_dir) and os.path.isdir(rst_module_dir)): self._is_cmake_source_tree = True self._cmake_help_module_dir = self._get_rst_module_dir(rst_module_filenm) assert os.path.exists(self._cmake_help_module_dir) and os.path.isdir(self._cmake_help_module_dir) else: self._is_cmake_source_tree = False self._cmake_help_module_dir = None def _get_rst_module_dir(self, rst_module_filenm): rst_manual_dir = os.path.dirname(rst_module_filenm) rst_module_dir = os.path.join(rst_manual_dir, '..', 'module') return os.path.normpath(rst_module_dir) def _check_section_title(self, section_title): if section_title in self._reserved_section_titles: raise InvalidInputParameterError("section {} is protected and cannot be modified, please contact technical support.".format(section_title)) def _check_extension_module_names(self, extension_module_names): if not self.is_cmake_source_tree(): return for mod_nm in extension_module_names: rst_module_file = os.path.join(self._cmake_help_module_dir, mod_nm + '.rst') if not os.path.exists(rst_module_file): raise Exception("file {} does not exist.".format(rst_module_file)) def _update_section(self, section_list, section_title, extension_module_names): section = None modified = False assert extension_module_names extension_module_names.sort() for sec in section_list: if sec.section_title == section_title: section = sec break if not section: # add a new section modified = True section = RstModuleSection() section.section_title = section_title section.section_title_marker_line = '{0:=>{width}}'.format(self._section_title_marker, width=len(section.section_title)) section.section_header.append('') section.section_header.append('.. toctree::') section.section_header.append(' :maxdepth: 1') section.section_header.append('') section_list.insert(0, section) else: # Section already present, update only if section content is different. existing_extension_module_names = [] # re_section_content = re.compile(r'\s+/module/([a-zA-Z0-9_-]+)\s*$') for line in section.section_content: re_match = self._re_section_content.match(line) if re_match: existing_extension_module_names.append(re_match.group(1)) existing_extension_module_names.sort() if len(existing_extension_module_names) != len(extension_module_names): modified = True else: for module_nm in existing_extension_module_names: if module_nm not in extension_module_names: modified = True break if modified: # replace the section section.section_content = [] if modified: # replace the content of an existing section for module_nm in extension_module_names: section.section_content.append(' /module/' + module_nm) return modified def _sort_section_list(self, section_list): """Sort section list by title and keep CMake's original sections at the end.""" section_list_ext = [] while section_list: sect = section_list[0] if sect.section_title in [self._section_title_cmake_modules_orig, self._section_title_cmake_modules]: break else: section_list_ext.append(sect) section_list.pop(0) section_title_dict = {} section_list_sorted = [] for sect in section_list_ext: section_title_dict[sect.section_title] = sect title_list = list(section_title_dict.keys()) title_list.sort() for title in title_list: section_list_sorted.append(section_title_dict[title]) # and append CMake's original sections. section_list_sorted.extend(section_list) return section_list_sorted def _parse_rst_module_file(self, rst_module_filenm): module_file_header = [] section_list = [] section = None previous_line = None re_empty_line = re.compile(r'^\s*$') with open(rst_module_filenm) as f: for line in f: line = line.rstrip() if not section_list: # Processing lines in front of the first section header if line.startswith(self._section_title_marker): section = RstModuleSection() section.section_title = previous_line section.section_title_marker_line = line self._logger.debug("found section: {}".format(previous_line)) section_list.append(section) # Remove the title line from the module header. module_file_header.pop() if module_file_header and re_empty_line.match(module_file_header[-1]): # Remove the last empty line from the module header to simplify saving sections later on. module_file_header.pop() else: module_file_header.append(line) else: if section.section_content: if self._re_section_content.match(line): section.section_content.append(line) else: section = RstModuleSection() else: # No section content found yet. if not section.section_title: if line.startswith(self._section_title_marker): section.section_title = previous_line section.section_title_marker_line = line section_list.append(section) self._logger.debug("found section: {}".format(previous_line)) else: pass else: if self._re_section_content.match(line): section.section_content.append(line) else: section.section_header.append(line) previous_line = line # self._dump_module_file_header(module_file_header) # self._dump_section_list(section_list) return module_file_header, section_list def _get_extension_module_names(self, section_list, section_title=None): extension_module_names = [] for sect in section_list: if sect.section_title in [self._section_title_cmake_modules_orig, self._section_title_cmake_modules]: continue if (section_title is None) or (section_title == sect.section_title): for line in sect.section_content: re_match = self._re_section_content.match(line) if re_match: extension_module_names.append(re_match.group(1)) return extension_module_names def _get_cmake_module_names(self, section_list): cmake_module_names = set() section_all_modules_fnd = False for sect in section_list: if not section_all_modules_fnd: if sect.section_title in [self._section_title_cmake_modules_orig, self._section_title_cmake_modules]: section_all_modules_fnd = True else: # One of the extension sections in front of "All Modules" or "Standard Modules" continue for line in sect.section_content: re_match = self._re_section_content.match(line) if re_match: cmake_module_names.add(re_match.group(1)) return cmake_module_names def _save_rst_module_file(self, output_rst_filenm, module_file_header, section_list): if self._dry_run: self._logger.debug("leaving without saving anything to %s", output_rst_filenm) return self._logger.debug("saving updated content to %s", output_rst_filenm) with open(output_rst_filenm, "w") as f: for line in module_file_header: f.write(line + '\n') for sect in section_list: f.write('\n') f.write(sect.section_title + '\n') f.write(sect.section_title_marker_line + '\n') for line in sect.section_header: f.write(line + '\n') for line in sect.section_content: f.write(line + '\n') def _remove_rst_extension_module_files(self, extension_module_names): if not self._autoremove: return if not self.is_cmake_source_tree(): return for mod_nm in extension_module_names: rst_module_file = os.path.join(self._cmake_help_module_dir, mod_nm + '.rst') if os.path.exists(rst_module_file): self._logger.debug("removing %s", rst_module_file) if not self._dry_run: os.remove(rst_module_file) def _dump_module_file_header(self, module_file_header): for line in module_file_header: print("file header: " + line) def _dump_section_list(self, section_list): print("number of sections: %d" %(len(section_list))) for section in section_list: print("section title: " + section.section_title) print("section title marker: " + section.section_title_marker_line) for line in section.section_header: print("section header: " + line) for line in section.section_content: print("section content: " + line)HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/cmkfnd.py000077500000000000000000000114361442026013100220750ustar00rootroot00000000000000 from __future__ import print_function import logging import os import re import subprocess import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver from pyhhi.build.common.system import SystemInfo class CMakeFinder(object): def __init__(self, sys_info=None): self._logger = logging.getLogger(__name__) if sys_info is None: self._sys_info = SystemInfo() else: self._sys_info = sys_info self._cmake_prog = None self._cmake_version = None self._cmake_search_path = self._sys_info.get_path() if self._sys_info.is_windows(): cmake_dir_list = [] cmake_inst_dir = self._query_winreg_cmake_inst_dir() if cmake_inst_dir is None: # cmake 3.6.1 is 64 bit but earlier cmake versions are 32 bit only. if self._sys_info.get_os_arch() == 'x86_64': cmake_dir_list.append(os.path.join(self._sys_info.get_program_dir('x86_64'), 'CMake', 'bin')) cmake_dir_list.append(os.path.join(self._sys_info.get_program_dir('x86'), 'CMake', 'bin')) for cmake_dir in cmake_dir_list: if os.path.exists(cmake_dir): if cmake_dir not in self._cmake_search_path: self._cmake_search_path.append(cmake_dir) else: # Append cmake install directory picked up from the registry (3.8.0 or higher). self._cmake_search_path.append(cmake_inst_dir) elif self._sys_info.is_macosx(): # The default installation path is /Applications/CMake.app/Contents/bin on MacOSX. cmake_dir = os.path.join('/Applications', 'CMake.app', 'Contents', 'bin') if os.path.exists(cmake_dir): if cmake_dir not in self._cmake_search_path: self._cmake_search_path.append(cmake_dir) elif self._sys_info.is_linux(): pass else: assert False def set_cmake_search_path(self, search_path): if search_path: self._cmake_search_path = search_path[:] self._logger.debug("cmake search path changed to: %s", ';'.join(self._cmake_search_path)) def find_cmake(self): """Returns the absolute path of a cmake executable.""" if self._cmake_prog is None: self._logger.debug("cmake search path: %s", ';'.join(self._cmake_search_path)) self._cmake_prog = util.find_tool_on_path('cmake', must_succeed=True, search_path=self._cmake_search_path) self._cmake_version = self._query_cmake_version(self._cmake_prog) return self._cmake_prog def is_cmake_installed(self): return self.find_cmake() is not None def get_cmake_version(self): assert self._cmake_version is not None return self._cmake_version def _query_cmake_version(self, cmake_cmd): retv = subprocess.check_output([cmake_cmd, '--version'], universal_newlines=True) return self._parse_cmake_version_retv(retv) def _parse_cmake_version_retv(self, retv): version_response = retv.rstrip() lines = version_response.splitlines() # Possible version information: # cmake version 3.7.2 # cmake version 3.8.0-rc2 # cmake3 version 3.6.3 # redhat 7.x cmake3 re_version_match = re.match(r'cmake\d*\s+version\s+([0-9]+\.[0-9]+\.[0-9]+)', lines[0], re.IGNORECASE) if not re_version_match: raise Exception("cmake has returned an unsupported version string. Please contact technical support.") self._logger.debug("cmake version: %s", re_version_match.group(1)) return ver.version_tuple_from_str(re_version_match.group(1)) def _query_winreg_cmake_inst_dir(self): cmake_install_dir = None if self._sys_info.is_python3(): import winreg win_registry = winreg else: import _winreg win_registry = _winreg reg_section = "SOFTWARE\\Kitware\\CMake" try: # rkey must be initialized in case OpenKey() does not return but raises an exception. rkey = None rkey = win_registry.OpenKey(win_registry.HKEY_LOCAL_MACHINE, reg_section) install_dir = win_registry.QueryValueEx(rkey, 'InstallDir')[0] if os.path.exists(os.path.join(install_dir, 'bin', 'cmake.exe')): cmake_install_dir = os.path.join(install_dir, 'bin') except WindowsError: if rkey is not None: win_registry.CloseKey(rkey) if cmake_install_dir: self._logger.debug("cmake install dir (winreg): %s", cmake_install_dir) else: self._logger.debug("cmake install dir (winreg): %s", "not found") return cmake_install_dir HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/cmksupp.py000077500000000000000000001010061442026013100223060ustar00rootroot00000000000000 from __future__ import print_function import logging import os import re import sys import pyhhi.build.common.bldtools as bldtools import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver from pyhhi.build.common.system import SystemInfo from pyhhi.build.cmkfnd import CMakeFinder class CMakeLauncherParams(object): def __init__(self): self.dry_run = False self.cmk_build = False self.clean_first = False # cmk_bin_dir override the default CMake search path. self.cmk_bin_dir = None self.cmk_build_jobs = 1 self.cmk_build_target = None #msbuild: verbosity levels: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic] self.cmk_build_verbosity = 'minimal' self.cmk_generator_alias = None self.cmk_warning_flags = [] self.cmk_cache_entries = [] # gcc, gcc-4.9, clang, msvc, msvc-19.0 self.toolset_str = None self.target_arch = None # tuple/list of build configurations (debug, release) self.build_configs = tuple(['debug']) self.link_variants = tuple(['static']) # Assigned if the script and its modules are to be installed. self.install_dir = None # Python directories to search for cache files/directories. self.py_cache_dirs = [] class CMakeCompilerInfo(object): def __init__(self): # If a toolchain file is given, all other attributes are not used and a cross compiler configuration # is assumed. self.cmake_toolchain_file = None # gcc, clang, msvc self.compiler_family = None self.version_major_minor = None self.target_arch = None self.cmake_cxx_compiler = None self.cmake_c_compiler = None self.mingw = False def is_cross_compiler(self): return self.cmake_toolchain_file is not None def __str__(self): if self.cmake_toolchain_file: s = "toolchain file: %s\n" % self.cmake_toolchain_file else: s = "compiler family: %s\n" % self.compiler_family s += "compiler version (major.minor): %s\n" % ver.version_tuple_to_str(self.version_major_minor) if self.target_arch: s += "target arch: %s\n" % self.target_arch if self.cmake_cxx_compiler: s += "cmake cxx compiler: %s\n" % self.cmake_cxx_compiler s += "cmake c compiler: %s\n" % self.cmake_c_compiler return s class CMakeBuildTreeInfo(object): def __init__(self, build_root, compiler_info, generator_alias): self._logger = logging.getLogger(__name__) self._sys_info = SystemInfo() self._build_root = build_root self._generator_alias = generator_alias self._default_build_configs = ['debug', 'release', 'relwithdebinfo', 'minsizerel'] # key=bld_variant.lnk_variant value=build_dir self._build_dir_dict = self._create_build_dir_dict(compiler_info, generator_alias, self._default_build_configs) def get_build_dir(self, bld_config, lnk_variant): return self._build_dir_dict[bld_config + '.' + lnk_variant] def is_multi_configuration_generator(self): return self._generator_alias.startswith('vs') or (self._generator_alias == 'xcode') def _create_build_dir_dict(self, compiler_info, generator_alias, build_configs): build_dir_dict = {} if compiler_info.is_cross_compiler(): assert generator_alias == 'umake' build_root = self._create_cross_compile_build_dir(self._build_root, compiler_info.cmake_toolchain_file, generator_alias) print("cross compile build root: " + build_root) if generator_alias == 'umake': for cfg in build_configs: build_dir_dict[cfg + '.' + 'static'] = os.path.join(build_root, cfg) build_dir_dict[cfg + '.' + 'shared'] = os.path.join(build_root, cfg + '-shared') else: target_arch = compiler_info.target_arch if compiler_info.mingw: toolset_dir = "{}-mingw-{}".format(compiler_info.compiler_family, ver.version_tuple_to_str(compiler_info.version_major_minor)) else: toolset_dir = "{}-{}".format(compiler_info.compiler_family, ver.version_tuple_to_str(compiler_info.version_major_minor)) if self.is_multi_configuration_generator(): for cfg in build_configs: build_dir_dict[cfg + '.' + 'static'] = os.path.join(self._build_root, generator_alias, toolset_dir, target_arch) build_dir_dict[cfg + '.' + 'shared'] = os.path.join(self._build_root, generator_alias, toolset_dir, target_arch + '-shared') else: for cfg in build_configs: build_dir_dict[cfg + '.' + 'static'] = os.path.join(self._build_root, generator_alias, toolset_dir, target_arch, cfg) build_dir_dict[cfg + '.' + 'shared'] = os.path.join(self._build_root, generator_alias, toolset_dir, target_arch, cfg + '-shared') return build_dir_dict def _create_cross_compile_build_dir(self, build_root, toolchain_file, generator_alias): assert generator_alias == 'umake' basenm = os.path.basename(toolchain_file) re_match = re.match(r'(.+)\.cmake$', basenm) if re_match: basenm = re_match.group(1) if self._sys_info.is_linux(): # Try to strip a distro related suffix. distro_suffix = self._sys_info.get_os_distro_short() re_match = re.match('(.+)[-]' + distro_suffix + '([-_.0-9]+)?$', basenm) if re_match: basenm = re_match.group(1) build_dir = os.path.join(build_root, basenm) return build_dir class CMakeLauncher(object): def __init__(self, verbosity=1): self._logger = logging.getLogger(__name__) self._sys_info = SystemInfo() self._verbosity_level = verbosity self._cmake_finder = CMakeFinder(self._sys_info) self._top_dir = None self._build_root = None self._build_tree_create_if_not_exists = True self._build_tree_info = None self._deploy_dir = None self._script_name = os.path.basename(sys.argv[0]) self._cmk_cache_file = 'CMakeCache.txt' # cache entries the user cannot override via -Dxxx self._cmk_reserved_cache_vars = ['BUILD_SHARED_LIBS', 'CMAKE_BUILD_TYPE', 'CMAKE_CONFIGURATION_TYPES', 'CMAKE_CXX_COMPILER', 'CMAKE_C_COMPILER', 'CMAKE_TOOLCHAIN_FILE'] self._dict_to_cmake_generator = {'umake': 'Unix Makefiles', 'mgwmake': 'MinGW Makefiles', 'ninja': 'Ninja', 'xcode': 'Xcode', 'vs16': 'Visual Studio 16 2019', 'vs15': 'Visual Studio 15 2017', 'vs14': 'Visual Studio 14 2015', 'vs12': 'Visual Studio 12 2013', 'vs11': 'Visual Studio 11 2012', 'vs10': 'Visual Studio 10 2010'} # list of default configuration types for multiconfiguration generators. self._default_config_types = ['debug', 'release'] # self._default_config_types = ['debug', 'release', 'relwithdebinfo'] self._dict_to_cmake_config = {'debug': 'Debug', 'release': 'Release', 'relwithdebinfo': 'RelWithDebInfo', 'minsizerel': 'MinSizeRel'} self._dict_to_vs_platform_name = {'x86_64': 'x64', 'x86': 'Win32'} self._prefer_vs_native_toolsets = True if self._sys_info.is_windows(): self._msvc_registry = bldtools.MsvcRegistry() self._dict_to_vs_platform_toolset = {'msvc-19.0': 'v140', 'msvc-18.0': 'v120', 'msvc-17.0': 'v110', 'msvc-16.0': 'v100'} self._dict_generator_alias_to_msvc_toolsets = {'vs14': ['msvc-19.0', 'msvc-18.0', 'msvc-17.0', 'msvc-16.0'], 'vs12': ['msvc-18.0', 'msvc-17.0', 'msvc-16.0'], 'vs11': ['msvc-17.0', 'msvc-16.0'], 'vs10': ['msvc-16.0']} # vs15 has not a fixed compiler version and therefore the mapping is generated dynamically. if self._msvc_registry.is_version_installed((14, 1)): cl_version = self._msvc_registry.get_compiler_version((14, 1)) msvc_str = 'msvc-' + ver.version_tuple_to_str(cl_version[:2]) if cl_version[1] < 20: self._dict_to_vs_platform_toolset[msvc_str] = 'v141' if not self._msvc_registry.is_vs2019_toolset((14, 1)): self._dict_generator_alias_to_msvc_toolsets['vs15'] = [msvc_str, 'msvc-19.0', 'msvc-18.0', 'msvc-17.0', 'msvc-16.0'] else: assert False # vs16 has not a fixed compiler version and therefore the mapping is generated dynamically. if self._msvc_registry.is_version_installed((14, 2)): cl_version = self._msvc_registry.get_compiler_version((14, 2)) msvc_str = 'msvc-' + ver.version_tuple_to_str(cl_version[:2]) if cl_version[1] < 30: self._dict_to_vs_platform_toolset[msvc_str] = 'v142' msvc_version_list = [msvc_str] if self._msvc_registry.is_version_installed((14, 1)): cl_version = self._msvc_registry.get_compiler_version((14, 1)) msvc_version_list.append("msvc-{0:d}.{1:d}".format(cl_version[0], cl_version[1])) msvc_version_list.extend(['msvc-19.0', 'msvc-18.0', 'msvc-17.0', 'msvc-16.0']) self._dict_generator_alias_to_msvc_toolsets['vs16'] = msvc_version_list else: assert False def launch(self, params, cmake_argv): if params.cmk_bin_dir: self._cmake_finder.set_cmake_search_path([params.cmk_bin_dir]) # Is cmake installed? if not self._cmake_finder.is_cmake_installed(): return self._top_dir = os.getcwd() self._build_root = os.path.join(self._top_dir, 'build') self._deploy_dir = os.path.join(self._top_dir, 'deploy') if not os.path.exists(self._build_root): os.makedirs(self._build_root) self._check_cmake_params(params) compiler_info = self._create_compiler_info(params.toolset_str, params.target_arch) #print(compiler_info) #return self._build_tree_info = CMakeBuildTreeInfo(self._build_root, compiler_info, params.cmk_generator_alias) #print(self._build_tree_info.get_build_dir('release', 'static')) #print(self._build_tree_info.get_build_dir('release', 'shared')) #print(self._build_tree_info.get_build_dir('debug', 'static')) #print(self._build_tree_info.get_build_dir('debug', 'shared')) # return if params.cmk_build: # cmake build if self._build_tree_create_if_not_exists and (not self._is_build_target_clean(params.cmk_build_target)): # cleaning a non-existing build tree is really a no-op and does not require a build tree at all. cmake_argv_config = [] if params.cmk_warning_flags: cmake_argv_config.extend(params.cmk_warning_flags) if params.cmk_cache_entries: cmake_argv_config.extend(params.cmk_cache_entries) for lnk in params.link_variants: self._create_default_build_tree(compiler_info, params.cmk_generator_alias, params.build_configs, lnk, cmake_argv_config) for lnk in params.link_variants: self.launch_build(params, lnk, cmake_argv) else: # cmake build tree create/update for lnk in params.link_variants: cmake_argv_config = [] if params.cmk_warning_flags: cmake_argv_config.extend(params.cmk_warning_flags) if params.cmk_cache_entries: cmake_argv_config.extend(params.cmk_cache_entries) if cmake_argv: cmake_argv_config.extend(cmake_argv) # print("warning flags: ", params.cmk_warning_flags) # print("additional flags: ", cmake_argv_config) self.launch_config(compiler_info, params.cmk_generator_alias, params.build_configs, lnk, cmake_argv_config) def launch_config(self, compiler_info, generator_alias, build_configs, lnk_variant, cmake_argv_optional): cur_dir = os.getcwd() cmake_argv = [] if self._is_multi_configuration_generator(): tmp_build_configs = [build_configs[0]] else: tmp_build_configs = build_configs for cfg in tmp_build_configs: b_dir = self._build_tree_info.get_build_dir(cfg, lnk_variant) if not os.path.exists(b_dir): os.makedirs(b_dir) if generator_alias.startswith('vs'): if compiler_info.compiler_family == 'msvc': if self._is_vs_64bit_native_toolset_supported(generator_alias): vs_toolset = self._dict_to_vs_platform_toolset['msvc-' + ver.version_tuple_to_str(compiler_info.version_major_minor)] + ',host=x64' else: vs_toolset = self._dict_to_vs_platform_toolset['msvc-' + ver.version_tuple_to_str(compiler_info.version_major_minor)] elif compiler_info.compiler_family == 'intel': vs_toolset = "Intel C++ Compiler %d.%d" % (compiler_info.version_major_minor[0], compiler_info.version_major_minor[1]) else: assert False cmake_argv = ['-G', self._dict_to_cmake_generator[generator_alias]] if generator_alias == 'vs16': if ver.version_compare(compiler_info.version_major_minor, (19, 20)) < 0: cmake_argv.extend(['-T', self._dict_to_vs_platform_toolset['msvc-' + ver.version_tuple_to_str(compiler_info.version_major_minor)]]) if compiler_info.target_arch != 'x86_64': cmake_argv.extend(['-A', self._dict_to_vs_platform_name[compiler_info.target_arch]]) else: cmake_argv.extend(['-T', vs_toolset, '-A', self._dict_to_vs_platform_name[compiler_info.target_arch]]) elif generator_alias == 'xcode': cmake_argv = ['-G', self._dict_to_cmake_generator[generator_alias]] elif generator_alias in ['umake', 'mgwmake', 'ninja']: cmake_argv = ['-G', self._dict_to_cmake_generator[generator_alias], '-DCMAKE_BUILD_TYPE:STRING=' + self._dict_to_cmake_config[cfg]] if compiler_info.is_cross_compiler(): cmake_argv.append('-DCMAKE_TOOLCHAIN_FILE:FILEPATH=' + compiler_info.cmake_toolchain_file) else: if compiler_info.cmake_cxx_compiler: cmake_argv.append('-DCMAKE_CXX_COMPILER:FILEPATH=' + compiler_info.cmake_cxx_compiler) if compiler_info.cmake_c_compiler: cmake_argv.append('-DCMAKE_C_COMPILER:FILEPATH=' + compiler_info.cmake_c_compiler) if cmake_argv_optional: # Add any additional arguments to the cmake command line. cmake_argv.extend(cmake_argv_optional) if lnk_variant == 'shared': cmake_argv.append('-DBUILD_SHARED_LIBS:BOOL=ON') if self._is_multi_configuration_generator(): cmake_config_types = [self._dict_to_cmake_config[x] for x in self._default_config_types] for b_cfg in build_configs: if b_cfg not in self._default_config_types: cmake_config_types.append(self._dict_to_cmake_config[b_cfg]) cmake_argv.append('-DCMAKE_CONFIGURATION_TYPES:STRING=' + ';'.join(cmake_config_types)) # cmake_argv.append(self._top_dir) # print("launch_config(): cmake_args", cmake_argv) # print("build dir:", b_dir) # print("top dir:", self._top_dir) if ver.version_compare(self._cmake_finder.get_cmake_version(), (3, 13, 0)) >= 0: cmake_argv.extend(['-S', self._top_dir, '-B', b_dir]) retv = self.launch_cmake(cmake_argv) else: os.chdir(b_dir) cmake_argv.append(os.path.relpath(self._top_dir)) retv = self.launch_cmake(cmake_argv) os.chdir(cur_dir) if retv != 0: sys.exit(1) def launch_build(self, params, lnk_variant, cmake_argv_optional): if self._is_multi_configuration_generator(): # multiple configurations / build directory b_dir = self._build_tree_info.get_build_dir(params.build_configs[0], lnk_variant) if self._is_build_target_clean(params.cmk_build_target) and (not os.path.exists(b_dir)): return for cfg in params.build_configs: cmake_argv = ['--build', b_dir, '--config', self._dict_to_cmake_config[cfg]] self._add_common_cmake_build_options(cmake_argv, params) self._add_cmake_build_jobs_option(cmake_argv, params.cmk_generator_alias, params.cmk_build_jobs) self._add_cmake_build_verbosity_option(cmake_argv, params.cmk_generator_alias, params.cmk_build_verbosity) if params.cmk_generator_alias.startswith('vs'): # msbuild option to disable node reuse -> jenkins build seems to idle at the end. self._add_cmake_build_tool_options(cmake_argv, ['/nr:false']) if cmake_argv_optional: self._add_cmake_build_tool_options(cmake_argv, cmake_argv_optional) retv = self.launch_cmake(cmake_argv) if retv != 0: sys.exit(1) else: # one build directory / configuration for cfg in params.build_configs: b_dir = self._build_tree_info.get_build_dir(cfg, lnk_variant) if self._is_build_target_clean(params.cmk_build_target) and (not os.path.exists(b_dir)): continue cmake_argv = ['--build', b_dir] self._add_common_cmake_build_options(cmake_argv, params) self._add_cmake_build_jobs_option(cmake_argv, params.cmk_generator_alias, params.cmk_build_jobs) self._add_cmake_build_verbosity_option(cmake_argv, params.cmk_generator_alias, params.cmk_build_verbosity) if cmake_argv_optional: self._add_cmake_build_tool_options(cmake_argv, cmake_argv_optional) retv = self.launch_cmake(cmake_argv) if retv != 0: sys.exit(1) def launch_cmake(self, cmake_argv): argv = [self._cmake_finder.find_cmake()] argv.extend(cmake_argv) if self._verbosity_level > 0: # assemble the cmake command line for logging purposes joiner = ' ' cmd_line = joiner.join(argv) print("Launching: " + cmd_line) retv = util.subproc_call_flushed(argv) if retv < 0: self._logger.debug("child was terminated by signal: %d", -retv) else: self._logger.debug("child returned: %d", retv) return retv def _is_build_target_clean(self, target): return (target is not None) and (target == 'clean') def _check_cmake_params(self, params): if params.cmk_generator_alias is None: if self._sys_info.is_windows_msys() and (params.toolset_str is not None) and (params.toolset_str == 'gcc'): params.cmk_generator_alias = 'umake' else: params.cmk_generator_alias = self._get_default_cmake_generator() if params.toolset_str is None: if self._sys_info.get_platform() == 'linux': params.toolset_str = 'gcc' elif self._sys_info.get_platform() == 'macosx': params.toolset_str = 'clang' elif self._sys_info.get_platform() == 'windows': if params.cmk_generator_alias in ['mgwmake', 'umake']: params.toolset_str = 'gcc' else: params.toolset_str = self._dict_generator_alias_to_msvc_toolsets[params.cmk_generator_alias][0] else: assert False elif params.toolset_str == 'msvc': # toolset=msvc means to select the latest msvc version the selected generator supports. assert self._sys_info.get_platform() == 'windows' params.toolset_str = self._dict_generator_alias_to_msvc_toolsets[params.cmk_generator_alias][0] elif params.toolset_str.startswith('msvc-'): if params.toolset_str not in self._dict_generator_alias_to_msvc_toolsets[params.cmk_generator_alias]: raise Exception("The selected generator does not support " + params.toolset_str + ", check toolset and generator arguments.") if params.target_arch is None: params.target_arch = self._sys_info.get_os_arch() if params.cmk_cache_entries: self._check_cmake_user_cache_entries(params.cmk_cache_entries) def _check_cmake_user_cache_entries(self, user_cache_entries): # -D:= or -D= provided by the user cannot override any reserved cache entries like BUILD_SHARED_LIBS, ... re_cache_entry = re.compile(r'-D(\w+)[=:]') for cache_opt in user_cache_entries: re_match = re_cache_entry.match(cache_opt) if re_match: cache_var = re_match.group(1) if cache_var in self._cmk_reserved_cache_vars: raise Exception("CMake cache entry " + cache_var + " is reserved by " + self._script_name + " and may not be overridden via -D, please contact technical support.") else: # Unexpected -D expression, please investigate. raise Exception("CMake cache entry expression " + cache_opt + " is unsupported, please contact technical support." ) def _get_default_cmake_generator(self): if 'DEFAULT_CMAKE_GENERATOR' in os.environ: generator_alias = os.environ['DEFAULT_CMAKE_GENERATOR'] if generator_alias not in self._dict_to_cmake_generator: raise Exception("CMake generator " + generator_alias + " defined by environment variable DEFAULT_CMAKE_GENERATOR is unsupported.") return generator_alias if self._sys_info.get_platform() == 'linux': generator_alias = 'umake' elif self._sys_info.get_platform() == 'macosx': generator_alias = 'xcode' elif self._sys_info.get_platform() == 'windows': # e.g. 14.2, 14.1, 14.0, 12.0 etc. bb_vs_latest_version = self._msvc_registry.get_latest_version() if ver.version_compare(bb_vs_latest_version, (14, 2)) == 0: generator_alias = 'vs16' elif ver.version_compare(bb_vs_latest_version, (14, 1)) == 0: generator_alias = 'vs15' else: generator_alias = 'vs' + str(bb_vs_latest_version[0]) else: assert False return generator_alias def _is_multi_configuration_generator(self): return self._build_tree_info.is_multi_configuration_generator() def _is_vs_64bit_native_toolset_supported(self, generator_alias): re_vs_generator = re.compile(r'vs(\d+)$') re_match = re_vs_generator.match(generator_alias) if not re_match: return False if not self._prefer_vs_native_toolsets: # Visual Studio native 64bit toolchains are disabled return False if self._sys_info.get_os_arch() != 'x86_64': return False if int(re_match.group(1), 10) < 12: # Visual Studio 11 2012 or earlier don't have native 64 bit toolchains. return False if ver.version_compare(self._cmake_finder.get_cmake_version(), (3, 8, 0)) < 0: # cmake too old to support vs native toolchains. return False return True def _create_compiler_info(self, toolset_str, target_arch): if self._sys_info.is_cray(): return self._create_cray_compiler_info(target_arch) compiler_info = CMakeCompilerInfo() if toolset_str and (toolset_str.endswith('.cmake')): # toolchain file specified -> no need to add any furter compiler details compiler_info.cmake_toolchain_file = toolset_str return compiler_info # native compiler selected or assumed, figure out details to create the build tree folder. compiler_info.target_arch = target_arch re_msvc_version = re.compile(r'msvc-(\d+\.\d+)$') re_match = re_msvc_version.match(toolset_str) if re_match: compiler_info.compiler_family = 'msvc' compiler_info.version_major_minor = ver.version_tuple_from_str(re_match.group(1)) return compiler_info else: assert not toolset_str.startswith('msvc') bb_toolset_info = bldtools.Toolset(self._sys_info, toolset_str) compiler_info.compiler_family = bb_toolset_info.get_toolset() compiler_info.version_major_minor = bb_toolset_info.get_version()[:2] # re_toolset_versioned = re.compile('([a-z]+)-(\d+\.\d+)$') if self._sys_info.get_platform() == 'linux': if toolset_str != 'gcc': compiler_info.cmake_cxx_compiler = bb_toolset_info.get_compiler_command() cxx_basename = os.path.basename(compiler_info.cmake_cxx_compiler) # print("cxx_basename: ", cxx_basename) if compiler_info.compiler_family == 'gcc': gcc_basename = cxx_basename.replace('g++', 'gcc') compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), gcc_basename) elif compiler_info.compiler_family == 'clang': clang_basename = cxx_basename.replace('++', '') compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), clang_basename) elif compiler_info.compiler_family == 'intel': compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), 'icc') elif self._sys_info.get_platform() == 'macosx': # assert compiler_info.compiler_family == 'clang' if compiler_info.compiler_family == 'clang': pass elif compiler_info.compiler_family == 'intel': compiler_info.cmake_cxx_compiler = bb_toolset_info.get_compiler_command() compiler_info.cmake_c_compiler = os.path.join(os.path.dirname(compiler_info.cmake_cxx_compiler), 'icc') else: assert False elif self._sys_info.get_platform() == 'windows': if compiler_info.compiler_family == 'msvc': pass elif compiler_info.compiler_family == 'gcc': # MinGW as native compiler: 64 bit and 32 bit default targets are possible. compiler_info.mingw = bb_toolset_info.is_mingw() compiler_info.target_arch = bb_toolset_info.get_platform_info(0).get_target_arch(0) elif compiler_info.compiler_family == 'intel': compiler_info.target_arch = bb_toolset_info.get_platform_info(0).get_target_arch(0) else: assert False return compiler_info def _create_cray_compiler_info(self, target): compiler_info = CMakeCompilerInfo() compiler_info.target_arch = target version_str = None if 'CRAY_PRGENVGNU' in os.environ: compiler_info.compiler_family = 'gcc' version_str = os.environ['GCC_VERSION'] elif 'CRAY_PRGENVCRAY' in os.environ: compiler_info.compiler_family = 'cray' version_str = os.environ['CRAY_CC_VERSION'] elif 'CRAY_PRGENVINTEL' in os.environ: compiler_info.compiler_family = 'intel' version_str = os.environ['INTEL_VERSION'] else: assert False version = ver.version_tuple_from_str(version_str) assert len(version) >= 2 compiler_info.version_major_minor = version[:2] return compiler_info def _create_default_build_tree(self, compiler_info, generator_alias, build_configs, lnk_variant, cmake_argv_optional): if self._is_multi_configuration_generator(): build_dir = self._build_tree_info.get_build_dir(build_configs[0], lnk_variant) if not self._is_valid_build_tree(build_dir): self.launch_config(compiler_info, generator_alias, build_configs, lnk_variant, cmake_argv_optional) else: for cfg in build_configs: build_dir = self._build_tree_info.get_build_dir(cfg, lnk_variant) if not self._is_valid_build_tree(build_dir): self.launch_config(compiler_info, generator_alias, [cfg], lnk_variant, cmake_argv_optional) def _is_valid_build_tree(self, build_dir): if os.path.exists(os.path.join(build_dir, self._cmk_cache_file)): return True if os.path.exists(build_dir): print(self._script_name + ": warning: build directory " + build_dir + " exists, but cmake cache file " + self._cmk_cache_file + " does not.") return False def _add_common_cmake_build_options(self, cmake_argv, params): if params.cmk_build_target: cmake_argv.extend(['--target', params.cmk_build_target]) if params.clean_first: cmake_argv.append('--clean-first') def _add_cmake_build_jobs_option(self, cmake_argv, generator_alias, build_jobs): cmake_version = self._cmake_finder.get_cmake_version() if ver.version_compare(cmake_version, (3, 12)) >= 0: assert len(cmake_argv) >= 2 if build_jobs >= 2: if generator_alias.startswith('vs'): self._add_cmake_build_tool_options(cmake_argv, ['/maxcpucount:' + str(build_jobs)]) else: cmake_argv.insert(2, str(build_jobs)) cmake_argv.insert(2, '--parallel') elif build_jobs == 0: # Use the build engine's native number of jobs. cmake_argv.insert(2, '--parallel') elif build_jobs >= 2: if generator_alias in ['umake', 'ninja']: self._add_cmake_build_tool_options(cmake_argv, ['-j' + str(build_jobs)]) elif generator_alias.startswith('vs'): self._add_cmake_build_tool_options(cmake_argv, ['/maxcpucount:' + str(build_jobs)]) elif generator_alias == 'xcode': self._add_cmake_build_tool_options(cmake_argv, ['-parallelizeTargets', '-jobs', str(build_jobs)]) def _add_cmake_build_verbosity_option(self, cmake_argv, generator_alias, verbosity_level): if verbosity_level == 'cmake': cmake_version = self._cmake_finder.get_cmake_version() if ver.version_compare(cmake_version, (3, 14)) >= 0: # self._add_cmake_build_tool_options(cmake_argv, ['-v']) # -v is a cmake option and not a build tool option and therefore # it has to be inserted left of '--' if '--' in cmake_argv: index = cmake_argv.index('--') cmake_argv.insert(index, '-v') else: cmake_argv.append('-v') else: if generator_alias.startswith('vs'): self._add_cmake_build_tool_options(cmake_argv, ['/verbosity:' + verbosity_level]) def _add_cmake_build_tool_options(self, cmake_argv, build_tool_options): if not build_tool_options: # no options given -> return return assert '--' not in build_tool_options if '--' not in cmake_argv: cmake_argv.append('--') cmake_argv.extend(build_tool_options) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/000077500000000000000000000000001442026013100215415ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/__init__.py000077500000000000000000000000001442026013100236430ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/android.py000077500000000000000000000317631442026013100235500ustar00rootroot00000000000000from __future__ import print_function import os import stat import re import shutil import subprocess import logging import pyhhi.build.common.system as system import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver class NdkFinder(object): def __init__(self, use_env=True): self._logger = logging.getLogger(__name__) self._sys_info = system.SystemInfo() self._use_env = use_env # check for ANDROID_NDK_ROOT when searching for NDK. self._re_ndk_root = re.compile(r'((android-ndk-r\d+([a-z]?))|(ndk-bundle))$') self._ndksa_root = os.path.join(self._sys_info.get_home_dir(), 'bin', 'ndk-sa') # set up a platform specific NDK search path if self._sys_info.is_macosx(): ndk_search_path = [os.path.join(self._sys_info.get_home_dir(), 'Library', 'Android', 'Sdk'), os.path.join(self._sys_info.get_home_dir(), 'Library'), self._sys_info.get_home_dir()] else: ndk_search_path = [os.path.join(self._sys_info.get_home_dir(), 'Android', 'Sdk'), self._sys_info.get_home_dir()] self._ndk_search_path = [d for d in ndk_search_path if os.path.exists(d)] self._logger.debug("NDK search path: " + ';'.join(self._ndk_search_path)) # (self._ndk_root, self._ndk_version) = self._find_ndk_root() self._ndk_platforms = self._query_platforms(self._ndk_root) self._ndksa_toolchains = {'gnustl': self._query_ndksa_toolchains(self.get_ndksa_root('gnustl')), 'libc++': self._query_ndksa_toolchains(self.get_ndksa_root('libc++'))} self._ndk_toolchain_dict = {'arm-linux-androideabi':'arm-linux-androideabi', 'aarch64-linux-android':'aarch64-linux-android', 'x86':'i686-linux-android', 'x86_64':'x86_64-linux-android'} def get_ndk_root(self): return self._ndk_root def get_ndk_version(self): return self._ndk_version def get_ndksa_root(self, stl='gnustl'): if stl: return os.path.join(self._ndksa_root, stl) else: return self._ndksa_root def get_ndksa_toolchains(self, stl='gnustl'): return self._ndksa_toolchains[stl] def get_ndk_platforms(self): return self._ndk_platforms def get_api_level_from_platform(self, platform): # platform := android-21, etc re_match = re.match(r'android-(\d+)$', platform) if re_match: return int(re_match.group(1)) else: raise Exception("Unsupported android platform specification encountered: " + platform) def create_ndksa_toolchain(self, ndk_toolchain, api_level=None, unified_headers=False, ndk_stl='gnustl', ndk_llvm_version=None, inst_dir=None): # whether bash scripts have proper hash bang lines or not. hash_bang_missing = False if ver.version_compare(self._ndk_version, (11,0)) < 0: hash_bang_missing = True # ndk_toolchain := arm-linux-androideabi-4.9, arm-linux-androideabi-clang3.6, arm-linux-androideabi # := arm-linux-androideabi-4.9 aarch64-linux-android-4.9 x86-4.9 x86_64-4.9 ndk_toolchain_parts = ndk_toolchain.split('-') if re.match('(clang)?[0-9.]+$', ndk_toolchain_parts[-1]): joiner = '-' ndk_toolchain_prefix = joiner.join(ndk_toolchain_parts[:-1]) else: ndk_toolchain_prefix = ndk_toolchain if ndk_toolchain_prefix in self._ndk_toolchain_dict: if inst_dir is None: ndksa_inst_dir = os.path.join(self.get_ndksa_root(ndk_stl), self._ndk_toolchain_dict[ndk_toolchain_prefix]) else: ndksa_inst_dir = os.path.join(inst_dir, ndk_stl, self._ndk_toolchain_dict[ndk_toolchain_prefix]) else: raise Exception("The NDK toolchain " + ndk_toolchain + " is not supported.") # Create a possibly patched version of the original script which can be invoked from python. mk_toolchain_script = self._create_mk_toolchain_script(self._ndk_root, hash_bang_missing) # build the argument vector mk_toolchain_args = [mk_toolchain_script] if api_level is None: api_level = self.get_api_level_from_platform(self._ndk_platforms[-1]) if (ver.version_compare(self._ndk_version, (14, 0)) >= 0) and (ver.version_compare(self._ndk_version, (16, 0)) < 0): if unified_headers: mk_toolchain_args.append('--unified-headers') if ver.version_compare(self._ndk_version, (12,0)) >= 0: # NDK 12 comes with a new python script expecting different command line options if ndk_toolchain_parts[0] == 'aarch64': ndk_arch = 'arm64' else: ndk_arch = ndk_toolchain_parts[0] mk_toolchain_args.append('--arch=' + ndk_arch) mk_toolchain_args.append('--api=' + str(api_level)) # --force -> remove destination directory if it exists. mk_toolchain_args.append('--force') else: ndk_platform = 'android-%d' % api_level mk_toolchain_args.append('--platform=' + ndk_platform) mk_toolchain_args.append('--toolchain=' + ndk_toolchain) if ver.version_compare(self._ndk_version, (11,0)) < 0: if ndk_llvm_version is not None: mk_toolchain_args.append('--llvm-version=' + ndk_llvm_version) else: # enable clang by default mk_toolchain_args.append('--use-llvm') if ndk_stl is not None: mk_toolchain_args.append('--stl=' + ndk_stl) mk_toolchain_args.append('--install-dir=' + ndksa_inst_dir) #print("create_ndksa_toolchain:", mk_toolchain_args) #return # prepare the destination directory if os.path.exists(ndksa_inst_dir): shutil.rmtree(ndksa_inst_dir) if not os.path.exists(self._ndksa_root): os.makedirs(self._ndksa_root) print("Launching: " + ' '.join(mk_toolchain_args)) # and launch the script to create the new toolchain util.subproc_check_call_flushed(mk_toolchain_args) if hash_bang_missing: if os.path.exists(mk_toolchain_script): os.remove(mk_toolchain_script) # patch the clang++ shell wrapper to have a hash bang self._patch_clang_shell_script(os.path.join(ndksa_inst_dir, 'bin', self._ndk_toolchain_dict[ndk_toolchain_prefix] + '-clang++')) self._patch_clang_shell_script(os.path.join(ndksa_inst_dir, 'bin', self._ndk_toolchain_dict[ndk_toolchain_prefix] + '-clang')) # update the list of available toolchains. self._ndksa_toolchains[ndk_stl] = self._query_ndksa_toolchains(os.path.join(ndksa_inst_dir, '..')) def _find_ndk_root(self): self._logger.debug("entering: use_env=" + str(self._use_env)) if self._use_env and ('ANDROID_NDK_ROOT' in os.environ): self._logger.debug("using environment variable ANDROID_NDK_ROOT") ndk_root = util.normalize_path(os.path.expandvars('$ANDROID_NDK_ROOT')) if not os.path.exists(ndk_root): raise Exception("environment variable ANDROID_NDK_ROOT points to a non-existing directory, please fix it or remove it.") ndk_version = self._query_ndk_version(ndk_root) else: # self._logger.warn("The environment variable NDK is not defined.") (ndk_root, ndk_version) = self._find_ndk_root_default(self._ndk_search_path) return ndk_root, ndk_version def _find_ndk_root_default(self, ndk_search_path): self._logger.debug("entering: ndk_search_path=" + ";".join(ndk_search_path)) # Search for android-ndk-r10d, android-ndk-r10, or similar and select the latest release. If the regular expressions matches, # there are always two groups but the second group is empty if no patch level is given. ndk_version_list = [] ndk_dir_map = {} for ndk_super_root in ndk_search_path: for d in os.listdir(ndk_super_root): re_match = self._re_ndk_root.match(d) if re_match: # the map associates a numeric version tuple with the NDK directory because the version sorter works on lists of numeric version tuples. ndk_root = os.path.join(ndk_super_root, d) ndk_version = self._query_ndk_version(ndk_root) if ndk_version not in ndk_dir_map: ndk_dir_map[ndk_version] = ndk_root ndk_version_list.append(ndk_version) self._logger.debug("find NDK " + ndk_root) else: self._logger.debug("duplicate NDK version encountered: " + ndk_root + " -> ignoring") if not ndk_version_list: raise Exception("The Android NDK installation directory cannot be found automatically, please contact technical support.") ndk_version_list = ver.version_list_sort(ndk_version_list) ndk_version = ndk_version_list[-1] ndk_root = ndk_dir_map[ndk_version] self._logger.debug("leaving, ndk_root=" + ndk_root) return ndk_root, ndk_version def _query_ndk_version(self, ndk_root): version_file = os.path.join(ndk_root, 'source.properties') if not os.path.exists(version_file): raise Exception("Android NDK version file " + version_file + " is missing, please contact technical support.") # Pkg.Revision = 11.2.2725575 re_ndk_version = re.compile(r'Pkg\.Revision\s*=\s*([0-9.]+)', re.IGNORECASE) with open(version_file) as vf: for line in vf: re_match = re_ndk_version.match(line) if re_match: ndk_version = ver.version_tuple_from_str(re_match.group(1)) return ndk_version raise Exception("Android NDK " + ndk_root + ": version information is missing. Please contact technical support.") def _query_platforms(self, ndk_root): platforms_dir = os.path.join(ndk_root, 'platforms') assert os.path.exists(platforms_dir) re_platform = re.compile('android-(\d+)$') # enumerate installed platforms in ascending order. version_list = [ver.version_tuple_from_str(re_platform.match(d).group(1)) for d in os.listdir(platforms_dir) if re_platform.match(d)] if version_list: version_list = ver.version_list_sort(version_list) ndk_platforms = ['android-' + ver.version_tuple_to_str(version) for version in version_list] return ndk_platforms else: assert False def _query_ndksa_toolchains(self, ndksa_root): ndksa_toolchains = [] if os.path.exists(ndksa_root): ndksa_toolchains = [d for d in os.listdir(ndksa_root) if os.path.isdir(os.path.join(ndksa_root, d))] return ndksa_toolchains def _create_mk_toolchain_script(self, ndk_root, hash_bang_missing): if ver.version_compare(self._ndk_version, (12, 0)) >= 0: mk_toolchain_script_basename = 'make_standalone_toolchain.py' else: mk_toolchain_script_basename = 'make-standalone-toolchain.sh' mk_toolchain_script = os.path.join(ndk_root, 'build', 'tools', mk_toolchain_script_basename) # print("mk_toolchain_script: " + mk_toolchain_script) assert os.path.exists(mk_toolchain_script) if hash_bang_missing: mk_toolchain_script_tmp = os.path.join(ndk_root, 'build', 'tools', 'make-standalone-toolchain.bash') self._add_bash_hash_bang(mk_toolchain_script, mk_toolchain_script_tmp) else: mk_toolchain_script_tmp = mk_toolchain_script return mk_toolchain_script_tmp def _patch_clang_shell_script(self, clang_script): if not os.path.exists(clang_script): return script_tmp = clang_script + '.tmp' self._add_bash_hash_bang(clang_script, script_tmp) assert os.path.exists(script_tmp) os.remove(clang_script) os.rename(script_tmp, clang_script) def _add_bash_hash_bang(self, script_old, script_new): if not os.path.exists(script_old): raise Exception("The script " + script_old + " does not exist.") # read the content of the original script input_lines = [] with open(script_old) as fin: for line in fin: input_lines.append(line.rstrip()) # create a new script with a hash bang if os.path.exists(script_new): os.remove(script_new) with open(script_new, "w") as fout: if not re.match(r'#!\s*/[a-zA-Z]+', input_lines[0]): fout.write("#!/bin/bash\n") for line in input_lines: fout.write(line + "\n") # make the script executable st = os.stat(script_new) os.chmod(script_new, st.st_mode | stat.S_IXUSR) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/bldtools.py000077500000000000000000002167221442026013100237520ustar00rootroot00000000000000from __future__ import print_function import glob import logging import os import platform import re import shutil import subprocess import sys import tempfile import textwrap import pyhhi.build.common.system as system import pyhhi.build.common.util as util import pyhhi.build.common.ver as ver class MsvcRegistry(object): class __MsvcRegistry(object): def __init__(self): self._logger = logging.getLogger(__name__) self._sys_info = system.SystemInfo() self._supported_msvc_versions = ['14.2', '14.1', '14.0', '12.0', '11.0', '10.0'] program_dir = self._sys_info.get_program_dir('x86') # VS2019, VS2017 come with a locator tool vswhere to search for the installation directory. # The dictionary _msvc_install_dir_dict will be augmented with keys 14.2 and 14.1 by method _do_inventory_vc14x(). self._msvc_install_dir_dict = {'14.0': [os.path.join(program_dir, "Microsoft Visual Studio 14.0", 'VC')], '12.0': [os.path.join(program_dir, "Microsoft Visual Studio 12.0", 'VC')], '11.0': [os.path.join(program_dir, "Microsoft Visual Studio 11.0", 'VC')], '10.0': [os.path.join(program_dir, "Microsoft Visual Studio 10.0", 'VC')]} # a list of sorted version tuples identifying the installed MSVC products self._installed_msvc_versions = [] # key = msvc_version, value = full path of vcvarsall.bat self._compiler_command_dict = {} # key = msvc_version, value = options to be passed to the setup command; e.g. -vcvars_ver=14.0, -vcvars_ver=14.1x self._compiler_command_option_dict = {} # key = msvc_version, value = vc version self._compiler_version_dict = {} # key = msvc_version, value = True/False self._is_vs2017_toolset_dict = {} # key = msvc_version, value = True/False; e.g. '14.1' -> True indicates 14.1 is an alternative toolset installed with vs2019. self._is_vs2019_toolset_dict = {} # clear information on alternative toolset upfront for version in self._supported_msvc_versions: self._is_vs2017_toolset_dict[version] = False self._is_vs2019_toolset_dict[version] = False if self._logger.isEnabledFor(logging.DEBUG): self._logger.debug("performing in-depth VS inventory for debugging.") self._do_inventory_winreg() vswhere = self._find_vswhere() if vswhere: # Update VS2019 installation paths via vswhere.exe self._do_inventory_vc14x('14.2', vswhere) # Update VS2017 installation paths via vswhere.exe self._do_inventory_vc14x('14.1', vswhere) else: pass self._do_inventory() self._dump_inventory() def _dump_inventory(self): if self._logger.isEnabledFor(logging.DEBUG): for version in self._installed_msvc_versions: version_str = ver.version_tuple_to_str(version) cl_version_str = ver.version_tuple_to_str(self._compiler_version_dict[version_str]) self._logger.debug("found MSVC version {}, CL version {}, setup={}".format(version_str, cl_version_str, self._compiler_command_dict[version_str])) def get_compiler_command(self, version=None): if version is None: version = self.get_latest_version() return self._compiler_command_dict[ver.version_tuple_to_str(version)] def get_compiler_version(self, version=None): if version is None: version = self.get_latest_version() return self._compiler_version_dict[ver.version_tuple_to_str(version)] def get_latest_version(self, max_version=None): if not self._installed_msvc_versions: raise Exception("No supported Microsoft Visual C++ version found, please check your installation or contact technical support.") if max_version is None: max_version = ver.version_tuple_from_str(self._supported_msvc_versions[0]) for version in self._installed_msvc_versions: if ver.version_compare(max_version, version) >= 0: return version raise Exception("No suitable Microsoft Visual C++ version found, please check your installation or contact technical support.") def is_version_installed(self, version): if (ver.version_compare(version, ver.version_tuple_from_str(self._supported_msvc_versions[0])) > 0) or (ver.version_compare(version, ver.version_tuple_from_str(self._supported_msvc_versions[-1])) < 0): raise Exception("Microsoft Visual C++ toolset msvc-" + ver.version_tuple_to_str(version) + " is not supported.") for v in self._installed_msvc_versions: if ver.version_compare(v, version) == 0: return True return False def is_vs2017_toolset(self, version): if not self.is_version_installed(version): return False version_str = ver.version_tuple_to_str(version) if version_str in self._is_vs2017_toolset_dict: return self._is_vs2017_toolset_dict[version_str] return False def is_vs2019_toolset(self, version): if not self.is_version_installed(version): return False version_str = ver.version_tuple_to_str(version) if version_str in self._is_vs2019_toolset_dict: return self._is_vs2019_toolset_dict[version_str] return False def _do_inventory(self): for version in self._supported_msvc_versions: if version not in self._msvc_install_dir_dict: continue setup_cmd = None for vc_dir in self._msvc_install_dir_dict[version]: self._logger.debug("trying VC install dir %s", vc_dir) # multiple vc install directories per version are possible to support community and professional/enterprise editions. cl_cmd = self._find_cl_cmd(vc_dir, version) if cl_cmd: self._logger.debug("found VC compiler %s", cl_cmd) if version in ['14.2', '14.1']: setup_cmd = os.path.normpath(os.path.join(os.path.dirname(cl_cmd), '..', '..', '..', '..', '..', '..', 'Auxiliary', 'Build', 'vcvarsall.bat')) elif version in ['14.0']: if os.path.exists(os.path.join(vc_dir, '..', 'Common7', 'IDE', 'devenv.exe')): self._logger.debug("found VS 2015 IDE installed.") setup_cmd = os.path.join(vc_dir, 'vcvarsall.bat') elif '14.2' in self._compiler_command_dict: # We've got 14.0 as an alternative VS 2019 toolset. self._logger.debug("found msvc-14.0 installed as an alternative VS 2019 toolset.") setup_cmd = self._compiler_command_dict['14.2'] self._is_vs2019_toolset_dict[version] = True self._compiler_command_option_dict[version] = '-vcvars_ver=14.0' elif '14.1' in self._compiler_command_dict: # We've got 14.0 as an alternative VS 2017 toolset. self._logger.debug("found msvc-14.0 installed as an alternative VS 2017 toolset.") setup_cmd = self._compiler_command_dict['14.1'] self._is_vs2017_toolset_dict[version] = True self._compiler_command_option_dict[version] = '-vcvars_ver=14.0' else: setup_cmd = os.path.join(vc_dir, 'vcvarsall.bat') break if (setup_cmd is not None) and os.path.exists(setup_cmd): assert cl_cmd is not None cl_version = self._query_msvc_compiler_version(cl_cmd) self._compiler_command_dict[version] = setup_cmd self._compiler_version_dict[version] = cl_version if (version == '14.2') and ('14.1' not in self._msvc_install_dir_dict): # Search for alternative toolset vc141 installed with vs2019 self._logger.debug("searching for alternative VS2019 toolset vc141.") vc_dir in self._msvc_install_dir_dict[version][0] setup_cmd = self._compiler_command_dict['14.2'] cl_cmd = self._find_cl_cmd(vc_dir, '14.1') if cl_cmd: self._logger.debug("found alternative VC compiler {}".format(cl_cmd)) cl_version = self._query_msvc_compiler_version(cl_cmd) self._compiler_command_dict['14.1'] = setup_cmd self._compiler_version_dict['14.1'] = cl_version self._compiler_command_option_dict['14.1'] = '-vcvars_ver=14.1x' self._is_vs2019_toolset_dict['14.1'] = True msvc_version_list = [] for version in self._compiler_version_dict: msvc_version_list.append(ver.version_tuple_from_str(version)) if msvc_version_list: self._installed_msvc_versions = ver.version_list_sort(msvc_version_list) self._installed_msvc_versions.reverse() # print("sorted msvc versions: ", self._installed_msvc_versions) def _find_cl_cmd(self, vc_inst_dir, version_str): cl_cmd = None if version_str in ['14.2', '14.1']: msvc_dir = os.path.join(vc_inst_dir, 'Tools', 'MSVC') if os.path.exists(msvc_dir): version_dir_list = [ver.version_tuple_from_str(x) for x in os.listdir(msvc_dir) if re.match(r'[0-9.]+$', x)] if version_dir_list: version_dir_list = ver.version_list_sort(version_dir_list) version_dir_list.reverse() # VS2019 installs toolset v141 side-by-side in a folder named '14.16.27023', toolset v142 is # installed in a folder named '14.20.27508'. for version in version_dir_list: if (version_str == '14.2') and (version[1] >= 30): self._logger.debug("ignoring cl installation folder: {}".format(os.path.join(msvc_dir, ver.version_tuple_to_str(version)))) continue if (version_str == '14.1') and (version[1] >= 20): self._logger.debug("ignoring cl installation folder: {}".format(os.path.join(msvc_dir, ver.version_tuple_to_str(version)))) continue cl_cmd = os.path.join(msvc_dir, ver.version_tuple_to_str(version), 'bin', 'HostX64', 'x64', 'cl.exe') if os.path.exists(cl_cmd): break else: cl_cmd = None else: cl_cmd = os.path.join(vc_inst_dir, 'bin', 'amd64', 'cl.exe') if not os.path.exists(cl_cmd): cl_cmd = None if cl_cmd: self._logger.debug("found cl: {}".format(cl_cmd)) return cl_cmd def _query_msvc_compiler_version(self, cl_cmd): version_file_dir = tempfile.mkdtemp() version_file = os.path.join(version_file_dir, 'vc_version_peek.h') with open(version_file, "w") as versionf: versionf.write(textwrap.dedent("""\ #pragma message(_MSC_FULL_VER _MSC_BUILD) """.format())) retv = subprocess.check_output([cl_cmd, '/EP', version_file], stderr=self._sys_info.get_subprocess_devnull(), universal_newlines=True).lstrip() # print("_query_msvc_compiler_versionf(): retv=" + retv) re_match = re.match(r'#pragma\s+message\(([0-9][0-9])([0-9][0-9])([0-9]+)\s+([0-9]+)\)', retv) if re_match: cl_version_str = "%s.%s.%s.%s" % (re_match.group(1), re_match.group(2), re_match.group(3), re_match.group(4)) # print("_query_msvc_compiler_cpp(): cl version: " + cl_version_str) cl_version = ver.version_tuple_from_str(cl_version_str) else: raise Exception("Failed to parse compiler version from " + version_file + ". Please contact technical support.") if os.path.exists(version_file): # print("temp. version file=" + version_file) shutil.rmtree(version_file_dir) return cl_version def _do_inventory_winreg(self): if int(platform.python_version_tuple()[0]) >= 3: import winreg win_registry = winreg else: import _winreg win_registry = _winreg msvc_registry_sections = ['Microsoft', 'Wow6432Node\\Microsoft'] reg_key_joiner = "\\" vc_install_dir_dict = {} for version in self._supported_msvc_versions: for section in msvc_registry_sections: try: sub_key = reg_key_joiner.join(['Software', section, 'VisualStudio', version, 'Setup', 'VC' ]) #print("_find_latest_msvc(): trying registry key:" + sub_key) rkey = win_registry.OpenKey(win_registry.HKEY_LOCAL_MACHINE, sub_key) #print("_find_latest_msvc(): found registry key:" + sub_key) vc_product_dir = win_registry.QueryValueEx(rkey, 'ProductDir')[0] vc_product_dir = util.normalize_path(vc_product_dir) if os.path.exists(os.path.join(vc_product_dir, 'vcvarsall.bat')): # check for vcvarsall.bat won't work as its existence won't indicate a complete installation of the development product. cl_cmd = self._find_cl_cmd(vc_product_dir, version) if (cl_cmd is not None) and os.path.exists(cl_cmd): vc_install_dir_dict[version] = util.normalize_path(vc_product_dir) self._logger.debug("found VC install dir %s", vc_install_dir_dict[version]) win_registry.CloseKey(rkey) except WindowsError: continue return vc_install_dir_dict def _do_inventory_vc14x(self, msvc_version_str, vswhere=None): if msvc_version_str == '14.2': vswhere_version_expr = '[16.0,17.0)' vs_alias_str = 'VS2019' elif msvc_version_str == '14.1': vswhere_version_expr = '[15.0,16.0)' vs_alias_str = 'VS2017' else: assert False if vswhere is None: vswhere = self._find_vswhere() if vswhere is None: self._logger.debug("{0} locator vswhere.exe not found, {0} detection disabled.".format(vs_alias_str)) return else: self._logger.debug("found {} locator: {}".format(vs_alias_str, vswhere)) vc_dir_fnd = False try: vswhere_argv = [vswhere, '-latest'] # vswhere_argv.extend(['-products', 'Enterprise']) # vswhere_argv.extend(['-products', 'Professional']) # vswhere_argv.extend(['-products', 'Community']) vswhere_argv.extend(['-products', '*']) vswhere_argv.extend(['-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64']) vswhere_argv.extend(['-property', 'installationPath']) vswhere_argv.extend(['-version', vswhere_version_expr]) retv = subprocess.check_output(vswhere_argv, universal_newlines=True).rstrip() if retv != '': self._logger.debug("{} install path: {}".format(vs_alias_str, retv)) vc_dir = os.path.join(retv, 'VC') if os.path.exists(vc_dir): self._logger.debug("{} VC install path: {}".format(vs_alias_str, vc_dir)) self._msvc_install_dir_dict[msvc_version_str] = [vc_dir] vc_dir_fnd = True else: self._logger.debug("{} install path: ".format(vs_alias_str)) except subprocess.CalledProcessError: self._logger.debug("{} vswhere locator call failed for some reason.".format(vs_alias_str)) if not vc_dir_fnd: self._logger.debug("{0} VC not found, {0} detection disabled.".format(vs_alias_str)) def _find_vswhere(self): vswhere_prog = None prog_dirs = [self._sys_info.get_program_dir('x86_64'), self._sys_info.get_program_dir('x86')] for d in prog_dirs: vswhere_dir = os.path.join(d, 'Microsoft Visual Studio', 'Installer') if os.path.exists(os.path.join(vswhere_dir, 'vswhere.exe')): vswhere_prog = os.path.join(vswhere_dir, 'vswhere.exe') break return vswhere_prog # the singleton as a class attribute instance = None def __init__(self): self._logger = logging.getLogger(__name__) if MsvcRegistry.instance is None: MsvcRegistry.instance = MsvcRegistry.__MsvcRegistry() def __getattr__(self, item): return getattr(MsvcRegistry.instance, item) class Toolset(object): class PlatformInfo(object): def __init__(self, target_os, api_level=None): # e.g. windows, linux, macosx, android, iphone, iphonesimulator self._target_os = target_os self._target_os_version = None self._api_level = api_level self._isysroot = None # The sdk_version attribute is only available on MacOSX. self._sdk_version = None self._target_archs = [] # Some compilers require extra flags to emit object code complying with a specific ABI or platform # specific SDK. self._target_cflags_dict = {} self._target_runtime_lib_dict = {} def get_target_os(self): return self._target_os def get_target_os_version(self): return self._target_os_version def set_target_os_version(self, version): self._target_os_version = version self.set_sdk_version(version) def get_sdk_version(self): return self._sdk_version def set_sdk_version(self, version): self._sdk_version = version def get_api_level(self): return self._api_level def set_api_level(self, api_level): self._api_level = api_level def get_isysroot(self): return self._isysroot def set_isysroot(self, isysroot): self._isysroot = isysroot def get_target_arch(self, index=None): if index is None: return self._target_archs else: return self._target_archs[index] def set_target_archs(self, target_archs): self._target_archs = target_archs def get_target_cflags(self, target_arch): if target_arch in self._target_cflags_dict: return self._target_cflags_dict[target_arch] else: return tuple() def set_target_cflags(self, target_arch, target_cflags): self._target_cflags_dict[target_arch] = target_cflags def get_target_runtime_libs(self, target_arch): if target_arch in self._target_runtime_lib_dict: return self._target_runtime_lib_dict[target_arch] else: return tuple() def set_target_runtime_libs(self, target_arch, target_runtime_libs): self._target_runtime_lib_dict[target_arch] = target_runtime_libs def __init__(self, sys_info, toolset=None, stl='default'): self._logger = logging.getLogger(__name__) self._sys_info = sys_info if stl == 'default': # only relevant for Android toolchains. stl = 'gnustl' if sys_info.is_windows(): self._msvc_registry = MsvcRegistry() self._toolset = None self._toolset_versioned = None self._toolset_info_short = None self._is_mingw = False # The ndk_finder attribute helps to qualify an Android toolset and will be created on first use. self._ndk_finder = None self._version = None self._internal_version = None # msvc only: version number reported by cl /? # A list of Platform objects self._platform_info = [] self._compiler_cmd = None self._compiler_prefix = None self._compiler_tag = None self._boost_compiler_tag = None self._lib_debug_tag = 'd' self._lib_prefix_shared = 'lib' self._lib_prefix_static = 'lib' self._intel_search_path = [] if sys_info.is_linux(): self._lib_ext_shared = ('.so', '.so') self._lib_ext_static = '.a' # Add Intel compiler search path if os.path.exists(os.path.join('/opt', 'intel', 'bin')): self._intel_search_path.append(os.path.join('/opt', 'intel', 'bin')) elif sys_info.is_macosx(): self._lib_ext_shared = ('.dylib', '.dylib') self._lib_ext_static = '.a' # Add Intel compiler search path self._intel_search_path.append(os.path.join('/usr', 'local', 'bin')) if os.path.exists(os.path.join('/opt', 'intel', 'bin')): self._intel_search_path.append(os.path.join('/opt', 'intel', 'bin')) elif sys_info.is_windows(): # Assume msvc naming convention as the default on windows self._lib_prefix_shared = '' self._lib_prefix_static = 'lib' self._lib_ext_shared = ('.dll', '.lib') self._lib_ext_static = '.lib' # Add Intel compiler search path intel_inst_root = os.path.join(self._sys_info.get_program_dir('x86'), 'IntelSWTools', 'compilers_and_libraries', 'windows', 'bin') if os.path.exists(os.path.join(intel_inst_root, 'intel64')): self._intel_search_path.append(os.path.join(intel_inst_root, 'intel64')) else: assert False # and set the toolset attributes with real values self._qualify_toolset(sys_info, toolset, stl) self._toolset_info_short = self._create_toolset_info_short() def __str__(self): s = "toolset: %s\n" % self._toolset s += "toolset versioned: %s\n" % self._toolset_versioned if self._internal_version: s += "version: %s [%s]\n" % (ver.version_tuple_to_str(self._version),ver.version_tuple_to_str(self._internal_version)) else: s += "version: %s\n" % ver.version_tuple_to_str(self._version) if self._toolset.startswith('msvc'): if self._msvc_registry.is_vs2017_toolset(self._version): s += "VS 2017 toolset!\n" if self._msvc_registry.is_vs2019_toolset(self._version): s += "VS 2019 toolset!\n" s += "platform(s):\n" for platform_info in self._platform_info: s += " target os: %s\n" % platform_info.get_target_os() target_os_version = platform_info.get_target_os_version() if target_os_version: s += " target os version: %s\n" % ver.version_tuple_to_str(target_os_version) sdk_version = platform_info.get_sdk_version() if sdk_version: s += " sdk version: %s\n" % ver.version_tuple_to_str(sdk_version) s += " target arch: %s\n" % platform_info.get_target_arch() for target in platform_info.get_target_arch(): cflags_tuple = platform_info.get_target_cflags(target) if cflags_tuple: cflags = ' '.join(cflags_tuple) s += " " + target + " => cflags: " + cflags + "\n" runtime_libs = platform_info.get_target_runtime_libs(target) for lib in runtime_libs: s += " rtl(" + target + "): " + lib + "\n" isysroot = platform_info.get_isysroot() if isysroot: s += " isysroot: %s\n" % isysroot s += "mingw?: %s\n" % self._is_mingw s += "compiler prefix: %s\n" % self._compiler_prefix s += "compiler command: %s\n" % self._compiler_cmd s += "compiler tag: %s\n" % self._compiler_tag s += "boost compiler tag: %s\n" % self._boost_compiler_tag s += "lib debug tag: %s\n" % self._lib_debug_tag s += "lib prefix shared: %s\n" % self._lib_prefix_shared s += "lib prefix static: %s\n" % self._lib_prefix_static s += "lib extension shared: %s %s\n" % self._lib_ext_shared s += "lib extension static: %s\n" % self._lib_ext_static return s def get_toolset_info_short(self, target_arch=None): """Returns a short description of the toolset.""" str = self._toolset_info_short # get the default platform platform_info = self.get_platform_info(0) if target_arch is None: target_arch = platform_info.get_target_arch(0) cflags_tuple = platform_info.get_target_cflags(target_arch) if cflags_tuple: str += '; ' str += 'toolset flags: ' + ' '.join(cflags_tuple) return str def get_toolset(self): """Returns the toolset string as understood by BoostBuild without a version suffix. The following toolsets are supported: msvc, gcc, clang.""" return self._toolset def get_version(self): return self._version def get_internal_version(self): return self._internal_version def get_toolset_versioned(self): """Returns the toolset string as understood by b2 with a version suffix. Example: msvc-11.0 or gcc-4.8""" return self._toolset_versioned def get_platform_info(self, index=None): """Returns a list of PlatformInfo objects or a single PlatformInfo object consisting of platform specific attributes. Example: clang may support platforms macosx, iphone and iphonesimulator.""" if index is None: return self._platform_info else: return self._platform_info[index] def is_mingw(self): return self._is_mingw def get_compiler_prefix(self): return self._compiler_prefix def get_compiler_command(self): """Returns the absolute path of the c++ compiler.""" return self._compiler_cmd def get_compiler_tag(self): return self._compiler_tag def get_boost_compiler_tag(self): return self._boost_compiler_tag def get_lib_debug_tag(self): return self._lib_debug_tag def get_lib_prefix_shared(self): return self._lib_prefix_shared def get_lib_prefix_static(self): return self._lib_prefix_static def get_lib_ext_shared(self): return self._lib_ext_shared def get_lib_ext_static(self): return self._lib_ext_static def _qualify_toolset(self, sys_info, toolset, stl='gnustl'): # toolset is either # 1) a toolset specification supported by Boost.Build: gcc-4.6, gcc, clang, msvc, msvc-x.y, darwin # 2) a relative compiler command: clang++, g++, g++-4.9, g++-5 # 3) an absolute compiler command if toolset is None: toolset = self._get_default_toolset(sys_info) # The relative compiler commands clang++, clang++-3.6, g++, g++-4.9 will be translated into the corresponding # Boost.Build toolset specifications. toolset = self._normalize_toolset_spec(toolset) if self._qualify_android_toolset(sys_info, toolset, stl): pass else: # Initialize the platform_info attributes for a native toolset. platform_info = self.PlatformInfo(sys_info.get_platform()) platform_info.set_target_archs([sys_info.get_os_arch()]) # Handle msvc upfront to simplify the logic. The msvc toolset implies desktop windows for the time # being. Portable platforms supported by msvc are not covered yet. if toolset.find('msvc') >= 0: self._toolset = 'msvc' if toolset == 'msvc': self._toolset_versioned = 'msvc-' + ver.version_tuple_to_str(self._msvc_registry.get_latest_version()) else: self._toolset_versioned = toolset re_match = re.match(r'msvc-([0-9.]+)$', self._toolset_versioned) if re_match: # make sure this version is installed if not self._msvc_registry.is_version_installed(ver.version_tuple_from_str(re_match.group(1))): raise Exception("Microsoft Visual C++ toolset msvc-" + re_match.group(1) + " is not installed.") # found a full product version, assume 32 and 64 bit compilers are available self._version = ver.version_tuple_from_str(re_match.group(1)) self._compiler_cmd = self._msvc_registry.get_compiler_command(self._version) if sys_info.get_os_arch() == 'x86_64': platform_info.set_target_archs(['x86', 'x86_64']) else: platform_info.set_target_archs(['x86']) self._platform_info.append(platform_info) # extract msvc/cl's internal version; e.g. 18.0.40629 self._internal_version = self._msvc_registry.get_compiler_version(self._version) else: raise Exception("The toolset " + toolset + " is not supported, please contact technical support.") else: if os.path.isabs(toolset): self._compiler_cmd = toolset else: if sys_info.is_macosx(): if toolset == 'clang': # Assume an Xcode toolchain, /usr/bin/clang++ will be ignored to support side-by-side installations of different Xcode toolchains. self._compiler_cmd = self._find_xcode_clang() elif toolset == 'darwin': self._compiler_cmd = util.find_tool_on_path('g++', True) elif toolset == 'intel': self._compiler_cmd = self._find_intel() else: raise Exception("The toolset " + toolset + " is not supported on MacOSX, please contact technical support.") else: # check for gcc-x.y and clang-x.y re_match = re.match(r'(gcc|clang)-([0-9.]+)$', toolset) if re_match: # self._toolset_versioned = toolset if re_match.group(1) == 'gcc': self._compiler_cmd = self._find_versioned_compiler('g++', ver.version_tuple_from_str(re_match.group(2))) elif re_match.group(1) == 'clang': self._compiler_cmd = self._find_versioned_compiler('clang++', ver.version_tuple_from_str(re_match.group(2))) else: assert False elif toolset == 'gcc': self._compiler_cmd = util.find_tool_on_path('g++', True) elif toolset == 'clang': self._compiler_cmd = self._find_clang() elif toolset == 'intel': self._compiler_cmd = self._find_intel() else: # toolset is supposed to be a c++ compiler command like g++-4.7, clang++-4.5 or some prefixed cross compiler. self._compiler_cmd = util.find_tool_on_path(toolset, True) # now guess the toolset category given the compiler command self._toolset = self._get_toolset_category(self._compiler_cmd) if self._toolset == 'clang': self._version = self._get_clang_version(self._compiler_cmd) elif self._toolset in ['gcc', 'darwin']: self._version = self._get_gcc_version(self._compiler_cmd) elif self._toolset == 'intel': self._version = self._get_intel_version(self._compiler_cmd) else: assert False # This does not work if /usr/bin/clang++ is linked to clang somewhere in the # filesystem. #if sys_info.is_linux() or sys_info.is_macosx(): # self._compiler_cmd = os.path.realpath(self._compiler_cmd) if self._toolset == 'darwin': self._platform_info.append(platform_info) elif self._toolset == 'clang': if sys_info.is_macosx(): (sdk_path, sdk_version) = self._discover_macosx_sdk(platform_info.get_target_os()) platform_info.set_isysroot(sdk_path) platform_info.set_target_os_version(sdk_version) self._platform_info.append(platform_info) # Add iphone platform information platform_info = self.PlatformInfo('iphone') platform_info.set_target_archs(['combined', 'armv7', 'arm64']) (sdk_path, sdk_version) = self._discover_macosx_sdk(platform_info.get_target_os()) platform_info.set_isysroot(sdk_path) platform_info.set_target_os_version(sdk_version) self._platform_info.append(platform_info) # Add iphonesimulator platform information platform_info = self.PlatformInfo('iphonesimulator') platform_info.set_target_archs(['combined', 'x86_64', 'x86']) (sdk_path, sdk_version) = self._discover_macosx_sdk(platform_info.get_target_os()) platform_info.set_isysroot(sdk_path) platform_info.set_target_os_version(sdk_version) self._platform_info.append(platform_info) elif sys_info.is_linux(): self._platform_info.append(platform_info) else: assert False elif self._toolset == 'gcc': # find out the compiler prefix if any. self._compiler_prefix = self._get_compiler_prefix(self._compiler_cmd) gcc_machine = self._get_machine(self._compiler_cmd) # analyze the compiler's machine string to understand what kind of cross compiler we've got. # e.g. ubuntu: x86_64-w64-mingw32 or i686-w64-mingw32 # windows: x86_64-w64-mingw32 # mingw32: mingw32 if re.search('mingw', gcc_machine): self._is_mingw = True platform_info = self.PlatformInfo('windows') if re.match('x86_64-', gcc_machine): if sys_info.is_windows(): # assume the 64 bit compiler can do 32 bit as well. platform_info.set_target_archs(['x86_64', 'x86']) else: platform_info.set_target_archs(['x86_64']) else: platform_info.set_target_archs(['x86']) elif re.match('arm-', gcc_machine): platform_info.set_target_archs(['arm']) elif re.match('aarch64-', gcc_machine): platform_info.set_target_archs(['aarch64']) self._platform_info.append(platform_info) elif self._toolset == 'intel': if sys_info.is_linux(): self._platform_info.append(platform_info) elif sys_info.is_macosx(): (sdk_path, sdk_version) = self._discover_macosx_sdk(platform_info.get_target_os()) platform_info.set_isysroot(sdk_path) platform_info.set_target_os_version(sdk_version) self._platform_info.append(platform_info) elif sys_info.is_windows(): #platform_info.set_target_archs(['x86_64', 'x86']) self._platform_info.append(platform_info) else: raise Exception("The toolset " + self._toolset + " is not supported on this platform yet, please contact technical support.") else: assert False # fill in the compiler taqs if self._toolset == 'msvc': self._compiler_tag = self._toolset_versioned self._boost_compiler_tag = 'vc' + str(self._version[0]) + str(self._version[1]) self._lib_debug_tag = 'gd' elif self._toolset == 'darwin': self._compiler_tag = 'gcc-' + ver.version_tuple_to_str(self._version[:2]) self._boost_compiler_tag = 'xgcc' + str(self._version[0]) + str(self._version[1]) elif self._toolset == 'clang': self._compiler_tag = 'clang-' + ver.version_tuple_to_str(self._version[:2]) if sys_info.is_macosx(): # The boost libraries are tagged with the version of the gcc backend and not the # clang version. gcc_version = self._get_gcc_version(self._compiler_cmd) self._boost_compiler_tag = 'clang-darwin' + str(gcc_version[0]) + str(gcc_version[1]) elif sys_info.is_linux(): self._boost_compiler_tag = 'clang' + str(self._version[0]) + str(self._version[1]) else: assert False elif self._toolset == 'gcc': if self._is_mingw: self._compiler_tag = 'gcc-mingw-' + ver.version_tuple_to_str(self._version[:2]) self._boost_compiler_tag = 'mgw' + str(self._version[0]) + str(self._version[1]) self._lib_prefix_shared = 'lib' self._lib_prefix_static = 'lib' self._lib_ext_shared = ('.dll', '.dll.a') self._lib_ext_static = '.a' self._add_mingw_runtime_lib_info(sys_info) else: self._compiler_tag = 'gcc-' + ver.version_tuple_to_str(self._version[:2]) self._boost_compiler_tag = 'gcc' + str(self._version[0]) + str(self._version[1]) elif self._toolset == 'intel': self._compiler_tag = 'intel-' + ver.version_tuple_to_str(self._version[:2]) if sys_info.is_linux() or sys_info.is_macosx(): self._boost_compiler_tag = 'il' + str(self._version[0]) + str(self._version[1]) elif sys_info.is_windows(): self._lib_debug_tag = 'gd' self._boost_compiler_tag = 'iw' else: assert False else: assert False def _normalize_toolset_spec(self, toolset): self._logger.debug("entering toolset=%s", toolset) # normalize a toolset specification like g++-4.9 to gcc-4.9 as understood by Boost.Build. if self._sys_info.is_macosx(): # deals with cmake which seems to detect c++ rather than clang++ on macosx. For some reason /usr/bin/c++ is linked to clang++ # and the same is true for the Xcode path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++. re_match = re.match(r'(clang|[cg])\+\+(-[0-9.]+)?', toolset, re.IGNORECASE) else: re_match = re.match(r'(clang|g)\+\+(-[0-9.]+)?', toolset, re.IGNORECASE) if re_match: toolset_norm = re_match.group(1) if toolset_norm == 'g': toolset_norm = 'gcc' elif toolset_norm == 'c': toolset_norm = 'clang' if re_match.group(2): toolset_norm += re_match.group(2) else: toolset_norm = toolset self._logger.debug("returning toolset=%s", toolset_norm) return toolset_norm def _get_toolset_category(self, compiler_cmd): assert os.path.isabs(compiler_cmd) basename = os.path.basename(compiler_cmd) if (basename.find('clang') >= 0) or (self._sys_info.is_macosx() and (basename == 'c++')): # deals with cmake which seems to detect c++ rather than clang++ on macosx. toolset_category = 'clang' elif (basename == 'icpc') or (basename == 'icl.exe'): toolset_category = 'intel' else: if self._sys_info.is_macosx(): if basename in ['g++', 'gcc']: toolset_category = 'darwin' else: toolset_category = 'gcc' else: toolset_category = 'gcc' return toolset_category def _add_mingw_runtime_lib_info(self, sys_info): if not sys_info.is_linux(): return # The LINUX mingw compilers are configured to link to the shared runtime by default, which has to be deployed to # the target system. if os.path.dirname(self.get_compiler_command()) != '/usr/bin': # Ignore this mingw compiler, it might be user private. return platform_info = self.get_platform_info(0) target_arch = platform_info.get_target_arch(0) compiler_prefix = self.get_compiler_prefix() compiler_version = ver.version_tuple_to_str(self.get_version()[:2]) re_dll_names = re.compile(r'((libstdc.*)|(libgcc_s_.*)|(libwinpthread.*))\.dll$', re.IGNORECASE) dir_list = [] if sys_info.get_os_distro() == 'ubuntu': # Ubuntu 15.04 # /usr/lib/gcc/x86_64-w64-mingw32/4.9-posix/libstdc++-6.dll # /usr/lib/gcc/x86_64-w64-mingw32/4.9-posix/libgcc_s_seh-1.dll # /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll # # Ubuntu 14.04 # /usr/lib/gcc/x86_64-w64-mingw32/4.8/libstdc++-6.dll # /usr/lib/gcc/x86_64-w64-mingw32/4.8/libgcc_s_sjlj-1.dll # /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll # thread_model = self._get_gcc_thread_model(self.get_compiler_command()) if thread_model == 'win32': # Assume thread model win32 without a dependency on libwinpthread. dir_list = [os.path.join('/usr/lib/gcc', compiler_prefix, compiler_version + '-win32')] else: # Assume thread model posix. dir_list = [os.path.join('/usr/lib/gcc', compiler_prefix, compiler_version), os.path.join('/usr/lib/gcc', compiler_prefix, compiler_version + '-posix'), os.path.join('/usr', compiler_prefix, 'lib')] elif sys_info.is_redhat(): retv = subprocess.check_output([self.get_compiler_command(), '-print-sysroot'], universal_newlines=True) sys_root = retv.lstrip().rstrip() if (len(sys_root) > 0) and os.path.exists(sys_root): dir_list = [os.path.join(sys_root, 'mingw', 'bin')] dll_list = [] for dir in dir_list: if os.path.exists(dir): file_list = [os.path.join(dir, f) for f in os.listdir(dir) if re_dll_names.match(f)] if file_list: dll_list.extend(file_list) if dll_list: #print('_add_mingw_runtime_lib_info', dll_list) platform_info.set_target_runtime_libs(target_arch, tuple(dll_list)) def _get_default_toolset(self, sys_info): toolset = None if 'BJAM_TOOLSET' in os.environ: # A power users can override the platform dependent default toolset via his environment. # # e.g. macosx: BJAM_TOOLSET=clang # windows: BJAM_TOOLSET=msvc-10.0 # toolset = os.environ['BJAM_TOOLSET'] else: if sys_info.is_linux(): toolset = 'gcc' elif sys_info.is_macosx(): #toolset = 'darwin' toolset = 'clang' elif sys_info.is_windows(): # the default toolset is the latest msvc. toolset = 'msvc-' + ver.version_tuple_to_str(self._msvc_registry.get_latest_version()) else: assert False return toolset def _get_gcc_version(self, gcc_cmd): # gcc -dumpversion may just emit the major version (g++-7/ubuntu 17.10) retv = subprocess.check_output([gcc_cmd, '-E', '-dM', '-x', 'c++', os.devnull], universal_newlines=True) lines = retv.splitlines() gcc_version_list = [0, 0, 0] re_gcc_version = re.compile(r'#define\s+(__GNUC__|__GNUC_MINOR__|__GNUC_PATCHLEVEL__)\s+(\d+)') for l in lines: re_match = re_gcc_version.match(l) if re_match: if re_match.group(1) == '__GNUC__': gcc_version_list[0] = int(re_match.group(2), 10) self._logger.debug("found gcc major %d", gcc_version_list[0]) elif re_match.group(1) == '__GNUC_MINOR__': gcc_version_list[1] = int(re_match.group(2), 10) self._logger.debug("found gcc minor %d", gcc_version_list[1]) elif re_match.group(1) == '__GNUC_PATCHLEVEL__': gcc_version_list[2] = int(re_match.group(2), 10) self._logger.debug("found gcc patch level %d", gcc_version_list[2]) version = tuple(gcc_version_list) return version def _get_gcc_thread_model(self, gcc_cmd): thread_model = 'posix' retv = subprocess.check_output([gcc_cmd, '-v'], stderr=subprocess.STDOUT, universal_newlines=True) lines = retv.splitlines() re_thread_model = re.compile(r'Thread model:\s*(\S+)', re.IGNORECASE) for l in lines: re_match = re_thread_model.match(l) if re_match: thread_model = re_match.group(1) return thread_model def _get_clang_version(self, clang_cmd): # ubuntu: Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0) # macosx: retv = subprocess.check_output([clang_cmd, '--version'], universal_newlines=True) version_response = retv.rstrip() lines = version_response.splitlines() re_version_match = re.search(r'\s+version\s+([0-9]+\.[0-9]+)', lines[0], re.IGNORECASE) if not re_version_match: raise Exception("The clang compiler has returned an unsupported version string. Please contact technical support.") return ver.version_tuple_from_str(re_version_match.group(1)) def _get_intel_version(self, icpc_cmd): if self._sys_info.is_windows(): re_version_match = None # stderr=subprocess.STDOUT: retv = subprocess.check_output([icpc_cmd, '/?'], stderr=subprocess.STDOUT, universal_newlines=True) version_response = retv.rstrip() lines = version_response.splitlines() re_version_match = re.search(r'\s+Version\s+([0-9.]+)', lines[0], re.IGNORECASE) else: retv = subprocess.check_output([icpc_cmd, '--version'], universal_newlines=True) version_response = retv.rstrip() lines = version_response.splitlines() re_version_match = re.match(r'^icpc\s+[^0-9.]+\s+([0-9.]+)', lines[0], re.IGNORECASE) if not re_version_match: raise Exception("The intel compiler has returned an unsupported version string. Please contact technical support.") return ver.version_tuple_from_str(re_version_match.group(1)) def _get_machine(self, gcc_cmd): retv = subprocess.check_output([gcc_cmd, '-dumpmachine'], universal_newlines=True) return retv.lower() def _get_compiler_prefix(self, compiler_cmd): # same for gcc and clang if os.path.isabs(compiler_cmd): compiler_cmd = os.path.basename(compiler_cmd) # arm-linux-gnueabihf-g++-4.8 # arm-linux-gnueabihf-g++ # arm-linux-androideabi-g++ # arm-linux-androideabi-g++-4.9 # i686-w64-mingw32-gcc-4.8 # i686-w64-mingw32-gcc # arm-linux-androideabi-clang compiler_cmd_parts = compiler_cmd.split('-') if len(compiler_cmd_parts) < 4: return None else: return '-'.join(compiler_cmd_parts[:3]) def _create_toolset_info_short(self): toolset_info = None if self._toolset == 'msvc': toolset_info = self._toolset + '-' + ver.version_tuple_to_str(self._version) if self._internal_version: toolset_info += ' [' + ver.version_tuple_to_str(self._internal_version) + ']' elif self._toolset in ['clang', 'darwin']: toolset_info = self._toolset + ' ' + ver.version_tuple_to_str(self._version) elif self._toolset == 'gcc': toolset_info = 'gcc ' + ver.version_tuple_to_str(self._version) if self._compiler_cmd != 'g++': toolset_info += ' using ' + self._compiler_cmd elif self._toolset == 'intel': toolset_info = 'intel ' + ver.version_tuple_to_str(self._version) else: assert False return toolset_info def _find_xcode_clang(self): retv = subprocess.check_output(['xcrun', '--sdk', 'macosx', '--find', 'clang++'], universal_newlines=True) clang_cmd = retv.lstrip().rstrip() if not os.path.exists(clang_cmd): raise Exception("Discovery of Xcode clang failed, please contact technical support.") return clang_cmd def _find_clang(self): if self._sys_info.is_linux(): clang_cmd = util.find_tool_on_path('clang++') if clang_cmd is None: # Try /usr/bin/clang++-x.y as a fallback, ubuntu clang packages may not add a link to the default version. clang_cmds = glob.glob('/usr/bin/clang++-[0-9]*') if clang_cmds: # select the highest version. re_clang_version = re.compile(r'.*\+\+-([0-9.]+)$') version_list = [] for clang in clang_cmds: re_match = re_clang_version.match(clang) if re_match: version_list.append(ver.version_tuple_from_str(re_match.group(1))) version_list = ver.version_list_sort(version_list) clang_cmd = '/usr/bin/clang++-' + ver.version_tuple_to_str(version_list[-1]) else: clang_cmd = util.find_tool_on_path('clang++') if clang_cmd is None: raise Exception("Discovery of clang++ failed, please check your installation or contact technical support.") return clang_cmd def _find_intel(self): icpc_cmd = None if self._intel_search_path: if self._sys_info.is_linux() or self._sys_info.is_macosx(): icpc_cmd = util.find_tool_on_path('icpc', search_path=self._intel_search_path) elif self._sys_info.is_windows(): icpc_cmd = util.find_tool_on_path('icl.exe', search_path=self._intel_search_path) else: assert False if icpc_cmd is None: raise Exception("Discovery of Intel compiler failed, please check your installation or contact technical support.") return icpc_cmd def _find_versioned_compiler(self, compiler_prog, toolset_version): """Find versioned compiler on the path.""" self._logger.debug("entering: compiler=%s %s", compiler_prog, ver.version_tuple_to_str(toolset_version)) compiler_cmd = util.find_tool_on_path(compiler_prog + '-' + ver.version_tuple_to_str(toolset_version)) if compiler_cmd: self._logger.debug("returning: %s", compiler_cmd) return compiler_cmd # Starting with g++ 5.x ubuntu systems use g++-5 instead of g++-.. compiler_cmd = util.find_tool_on_path(compiler_prog + '-' + str(toolset_version[0])) if compiler_cmd is None: # Search for the compiler without a version suffix but make sure its version matches the toolset version compiler_cmd = util.find_tool_on_path(compiler_prog, True) self._logger.debug("con't validating version of %s, expected: %s", compiler_cmd, ver.version_tuple_to_str(toolset_version)) version = None if compiler_prog.startswith('g++'): version = self._get_gcc_version(compiler_cmd) elif compiler_prog.startswith('clang++'): version = self._get_clang_version(compiler_cmd) else: assert False if version: assert len(version) >= 2 if ver.version_compare(version[:2], toolset_version) != 0: raise Exception("Search for compiler command " + compiler_prog + " version " + ver.version_tuple_to_str(toolset_version) + " failed, please contact technical support.") self._logger.debug("returning: %s", compiler_cmd) return compiler_cmd def _discover_macosx_sdk(self, target_os): sdk_version = None if target_os == 'macosx': sdk = target_os elif target_os == 'iphone': sdk = 'iphoneos' elif target_os == 'iphonesimulator': sdk = target_os else: assert False retv = subprocess.check_output(['xcrun', '--sdk', sdk, '--show-sdk-path'], universal_newlines=True) sdk_path = retv.lstrip().rstrip() if not os.path.exists(sdk_path): raise Exception("The location of the platform SDK cannot be discovered, please contact technical support.") sdk_basename = os.path.basename(sdk_path) re_match = re.match(r'[^0-9]+(\d+\.\d+)\.sdk$', sdk_basename, re.IGNORECASE) if re_match: sdk_version = ver.version_tuple_from_str(re_match.group(1)) return (sdk_path, sdk_version) def _qualify_android_toolset(self, sys_info, toolset, stl='gnustl'): if sys_info.is_windows(): # No Android support on windows yet. return False # All android cross compilers are supposed to be named '[path]*android*'. if os.path.isabs(toolset): toolset_cmd = os.path.basename(toolset) else: toolset_cmd = toolset if toolset_cmd.find('android') < 0: return False if os.path.isabs(toolset): toolset_cmd = toolset else: # toolset is supposed to be a prefixed g++ or possibly clang++ command. toolset_cmd = util.find_tool_on_path(toolset) if toolset_cmd is None: # analyze toolset and search for -android or -androideabi toolset_prefix_list = toolset.split('-') if len(toolset_prefix_list) < 4: return False if re.match('android', toolset_prefix_list[2]): # android or androideabi toolchain_prefix = '-'.join(toolset_prefix_list[:3]) ndk_finder = self._get_ndk_finder() toolset_cmd = os.path.join(ndk_finder.get_ndksa_root(stl), toolchain_prefix, 'bin', toolset) assert os.path.exists(toolset_cmd) else: return False toolset_machine = self._get_machine(toolset_cmd) if re.search('-android', toolset_machine): toolset_machine_parts = toolset_machine.split('-') if len(toolset_machine_parts) < 3: return False # Looks like this toolset is really a supported Android toolset, initialize all attributes. self._compiler_cmd = toolset_cmd self._compiler_prefix = self._get_compiler_prefix(toolset_cmd) if re.match(r'.*((clang)|(clang\+\+))$', toolset_cmd): self._toolset = 'clang' else: self._toolset = 'gcc' platform_info = self.PlatformInfo('android', self._get_android_api_level(toolset_cmd)) if re.match('(armv5te)|(armv7a)|(arm)$', toolset_machine_parts[0]): #armeabi armeabi-v7a armeabi-v7a-hard platform_info.set_target_archs(['armeabi-v7a', 'armeabi']) platform_info.set_target_cflags('armeabi-v7a', tuple(['-march=armv7-a', '-mfloat-abi=softfp', '-mfpu=vfpv3-d16'])) elif toolset_machine_parts[0] == 'aarch64': platform_info.set_target_archs(['arm64-v8a']) elif toolset_machine_parts[0] == 'i686': platform_info.set_target_archs(['x86']) elif toolset_machine_parts[0] == 'x86_64': platform_info.set_target_archs(['x86_64']) else: assert False self._platform_info.append(platform_info) if self._toolset == 'gcc': self._version = self._get_gcc_version(toolset_cmd) self._compiler_tag = 'gcc-' + ver.version_tuple_to_str(self._version[:2]) self._boost_compiler_tag = 'gcc' + str(self._version[0]) + str(self._version[1]) elif self._toolset == 'clang': self._version = self._get_clang_version(toolset_cmd) self._compiler_tag = 'clang-' + ver.version_tuple_to_str(self._version[:2]) if sys_info.is_macosx(): # The boost libraries are tagged with the version of the gcc backend and not the # clang version. gcc_version = self._get_gcc_version(self._compiler_cmd) self._boost_compiler_tag = 'clang-darwin' + str(gcc_version[0]) + str(gcc_version[1]) else: self._boost_compiler_tag = 'clang' + str(self._version[0]) + str(self._version[1]) else: assert False return True else: assert False def _get_ndk_finder(self): if self._ndk_finder is None: import pyhhi.build.common.android self._ndk_finder = pyhhi.build.common.android.NdkFinder() return self._ndk_finder def _get_android_api_level(self, toolset_cmd): # toolset_cmd is supposed to be an absolute path to be able to support different API levels and # architectures. If the toolset command refers to a standalone toolchain, there is a single api-level header and # the API level can be extracted unless unified headers are used. # If the toolset command refers to the NDK compiler (->QtCreator), the latest API level will be # taken as default. api_level_header = os.path.join(os.path.dirname(toolset_cmd), '..', 'sysroot', 'usr', 'include', 'android', 'api-level.h') if os.path.exists(api_level_header): # This looks like a standalone toolchain installation. # #define __ANDROID_API__ 21 re_api_define = re.compile(r'^#define\s+__ANDROID_API__\s+(\d+)') with open(api_level_header) as fin: for line in fin: re_match = re_api_define.match(line) if re_match: api_level = int(re_match.group(1), 10) return api_level # Most likely NDK r15 with unified headers, the API level is now defined in arm-linux-androideabi-clang++. ndk_finder = self._get_ndk_finder() ndk_version = ndk_finder.get_ndk_version() if ver.version_compare(ndk_version, (15, 0)) >= 0: return self._get_android_api_level_unified(toolset_cmd) raise Exception("The Android API level cannot be extracted from " + api_level_header + ". Please contact technical support.") else: # Assume the original NDK toolchain with multiple platform/API level support ndk_finder = self._get_ndk_finder() ndk_platforms = ndk_finder.get_ndk_platforms() re_match = re.match(r'android-(\d+)', ndk_platforms[-1]) if re_match: api_level = int(re_match.group(1), 10) else: raise Exception("The Android API level cannot be determined, please contact technical support.") return api_level def _get_android_api_level_unified(self, toolset_cmd): if toolset_cmd.endswith('clang++') or toolset_cmd.endswith('clang'): # -D__ANDROID_API__=26 re_api_level_def = re.compile(r'\s+-D__ANDROID_API__=(\d+)') with open(toolset_cmd) as fin: for line in fin: re_match = re_api_level_def.search(line) if re_match: api_level = int(re_match.group(1), 10) return api_level raise Exception("The Android API level cannot be determined. Please contact technical support.") class FatBinaryTool(object): def __init__(self): # search for lipo and raise an Exception if the command cannot be found. self._lipo_cmd = util.find_tool_on_path('lipo', True) def createLibs(self, src_lib_dirs, dst_lib_dir, incremental=True): if len(src_lib_dirs) < 2: raise Exception("A universal library requires at least two different input formats.") for d in src_lib_dirs: if not os.path.exists(d): raise Exception("The directory " + d + " does not exist.") if not os.path.exists(dst_lib_dir): os.makedirs(dst_lib_dir) lib_dir = src_lib_dirs[0] lib_names = [d for d in os.listdir(lib_dir) if (d.endswith('.a') or d.endswith('.dylib'))] for lib in lib_names: src_mtime = 0 src_libs = [] for d in src_lib_dirs: src_lib = os.path.join(d, lib) if os.path.exists(src_lib): mtime = os.path.getmtime(src_lib) if mtime > src_mtime: src_mtime = mtime src_libs.append(src_lib) if len(src_libs) >= 2: lipo_argv = [self._lipo_cmd, '-create'] lipo_argv.extend(src_libs) dst_lib = os.path.join(dst_lib_dir, lib) lipo_argv.extend(['-output', dst_lib]) build_universal = True if os.path.exists(dst_lib): mtime = os.path.getmtime(dst_lib) if incremental and (mtime > src_mtime): build_universal = False if build_universal: # and launch lipo to create the universal binary file. cmd_line = ' '.join(lipo_argv) print("Launching: " + cmd_line) retv = util.subproc_call_flushed(lipo_argv) if retv != 0: raise Exception("Creating a universal file failed -> " + cmd_line) else: raise Exception("error: creating a univeral file requires at least two input files, check " + lib) class DyLibInstallNameInfo(object): def __init__(self, dylib): assert os.path.exists(dylib) self.basename = os.path.basename(dylib) self.inst_dir = os.path.dirname(dylib) self.inst_name = None self.depends_list = [] self.rpath_list = [] class DyLibInstallNameInfoInspector(object): def __init__(self, ignore_system_libs=True): self._ignore_system_libs = ignore_system_libs self._inst_name_info_cache = {} def create_install_name_info(self, dylib): assert os.path.exists(dylib) if not os.path.isabs(dylib): dylib = os.path.abspath(dylib) if dylib not in self._inst_name_info_cache: inst_name_info = DyLibInstallNameInfo(dylib) inst_name_info.inst_name = self.get_install_name(dylib) (depends_list, rpath_list) = self.get_depends_list(dylib) inst_name_info.depends_list = depends_list inst_name_info.rpath_list = rpath_list self._inst_name_info_cache[dylib] = inst_name_info else: inst_name_info = self._inst_name_info_cache[dylib] return inst_name_info def get_install_name(self, dylib): assert os.path.exists(dylib) lines = subprocess.check_output(['otool', '-D', dylib], universal_newlines=True).rstrip().splitlines() return lines[1] def get_depends_list(self, dylib): assert os.path.exists(dylib) depends_list = [] rpath_list = [] load_cmd_lines = subprocess.check_output(['otool', '-l', dylib], universal_newlines=True).rstrip().splitlines() re_depends_path = re.compile(r'\s*name\s+([^ ]+)') re_rpath = re.compile(r'\s*path\s+([^ ]+)') # otool -L dylib -> # lib/clang-4.2/x86_64/plugins/debug/codec/libmpg4nulldec_plugin.dylib: # libmpg4nulldec_plugin.dylib (compatibility version 0.0.0, current version 0.0.0) # @loader_path/lib/libvlccore.5.dylib (compatibility version 7.0.0, current version 7.0.0) # /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0) # /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0) # # -- # otool -l dylib -> # cmd LC_RPATH # cmdsize 80 # path /Users/rauthenberg/projects/VlcPluginSampleLib/lib/clang-6.1/x86_64 (offset 12) # # cmd LC_LOAD_DYLIB # cmdsize 48 # name /usr/lib/libc++.1.dylib (offset 24) # re_lc_rpath = re.compile(r'\s*cmd\s+LC_RPATH') re_lc_load_dylib = re.compile(r'\s*cmd\s+LC_LOAD_DYLIB') line_cnt = 0 while line_cnt < len(load_cmd_lines): line = load_cmd_lines[line_cnt].lstrip() if re_lc_rpath.match(line): re_match = re_rpath.match(load_cmd_lines[line_cnt + 2]) if re_match: rpath_list.append(re_match.group(1)) line_cnt += 3 elif re_lc_load_dylib.match(line): re_match = re_depends_path.match(load_cmd_lines[line_cnt + 2]) if re_match: depends_path = re_match.group(1) if self._ignore_system_libs: if not depends_path.startswith(('/System/', '/Library/', '/usr/lib/')): depends_list.append(depends_path) else: depends_list.append(depends_path) line_cnt += 3 else: line_cnt += 1 return (depends_list, rpath_list) def modify_depends(self, dylib, depends_dict): argv = ['install_name_tool'] for key in depends_dict: argv.append('-change') argv.append(key) argv.append(depends_dict[key]) argv.append(dylib) #print("modify_depends(): ", argv) util.subproc_check_call_flushed(argv) def change_rpaths(self, dylib, rpaths_dict): argv = ['install_name_tool'] for key in rpaths_dict: argv.append('-rpath') argv.append(key) argv.append(rpaths_dict[key]) argv.append(dylib) #print("change_rpaths(): ", argv) util.subproc_check_call_flushed(argv) def delete_rpaths(self, dylib, rpath_list): argv = ['install_name_tool'] for rpath in rpath_list: argv.append('-delete_rpath') argv.append(rpath) argv.append(dylib) #print("change_rpaths(): ", argv) util.subproc_check_call_flushed(argv) def modify_install_name(self, dylib, install_name): argv = ['install_name_tool', '-id', install_name, dylib] util.subproc_check_call_flushed(argv) class BuildScriptInstaller(object): def __init__(self, verbose=False): self._logger = logging.getLogger(__name__) # print("BuildScriptInstaller.__init__(): __name__=" + __name__) self._verbose = verbose def set_verbose(self, verbose): self._verbose = verbose def install_script(self, inst_dir, script, modules): assert inst_dir is not None script = os.path.abspath(script) module_flist = [] package_dir_set = set() # python modules are specified in import syntax like ".". for pymod in modules: pymod_elem = pymod.split('.') rel_path = os.path.sep.join(pymod_elem) module_flist.append(rel_path + '.py') if len(pymod_elem) > 1: # module is part of a python package pkg_list = list(pymod_elem[:-1]) #print("processing python package dir list", pkg_list) while len(pkg_list) > 0: pkg_dir = os.path.sep.join(pkg_list) #print("processing pkg dir", pkg_dir) if pkg_dir not in package_dir_set: package_dir_set.add(pkg_dir) pkg_list.pop() for pkg_dir in package_dir_set: #print("processing pkg dir", pkg_dir) module_flist.append(os.path.join(pkg_dir, '__init__.py')) #print("install_script: modules:", module_flist) # make sure all files exist before trying to copy anything. if not os.path.exists(script): raise Exception("file " + script + " does not exist.") # key = module_file_path, value = file system path # e.g. pyhhi/build/common/ver.py must be mapped to a directory listed by sys.path. module_flist_src_dict = {} for f in module_flist: for pth in sys.path: fpath = os.path.join(pth, f) if os.path.exists(fpath): module_flist_src_dict[f] = fpath break else: fpath = None if fpath is None: raise Exception("module file {0} not found.".format(fpath)) # create destination directory if not os.path.exists(inst_dir): os.makedirs(inst_dir) for f in module_flist: assert f in module_flist_src_dict fpath_src = module_flist_src_dict[f] dname = os.path.dirname(f) dst_dir = os.path.join(inst_dir, dname) #print("cp " + fpath_src + " -> " + os.path.join(dst_dir, dname)) if not os.path.exists(dst_dir): os.makedirs(dst_dir) #print("creating directory " + dst_dir) if self._verbose: print("copying %-15s %s" % (os.path.basename(fpath_src), dst_dir)) shutil.copy(fpath_src, dst_dir) # copy the script to if self._verbose: print("copying %-15s %s" % (os.path.basename(script), inst_dir)) shutil.copy(script, inst_dir) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/cmbldver.py000077500000000000000000000002671442026013100237210ustar00rootroot00000000000000 #-- WARNING -- # This file is automatically generated by CMake. # Any manual changes here will be overridden by the next build. #------------- CMAKE_BUILD_VERSION_STR = "3.14.4.4" HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/error.py000077500000000000000000000015741442026013100232560ustar00rootroot00000000000000 class BaseError(Exception): """Base exception with a hint whether to list traceback information or not. Attributes: msg -- explanation of the error list_traceback -- hint to an application level exception handler whether to list traceback information or not. """ def __init__(self, msg, list_traceback=True): self.msg = msg self.list_traceback = list_traceback def __str__(self): return self.msg class InvalidInputParameterError(BaseError): """Exception raised for invalid input parameters.""" def __init__(self, msg, list_traceback=False): BaseError.__init__(self, msg, list_traceback) class InvalidCommandLineArgumentError(BaseError): """Exception raised for invalid command line arguments.""" def __init__(self, msg, list_traceback=False): BaseError.__init__(self, msg, list_traceback) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/system.py000077500000000000000000000530221442026013100234440ustar00rootroot00000000000000 from __future__ import print_function import multiprocessing import logging import platform import os import sys import re import shutil import tempfile import textwrap import subprocess import pyhhi.build.common.ver as ver import pyhhi.build.common.util as util class SystemInfo(object): class __SystemInfo(object): def __init__(self): self._logger = logging.getLogger(__name__) # print("Constructing a new SystemInfo object") # check python version: it has to be 2.7 or higher self._python_version = ver.get_python_version(True) # create all attributes with default values which will be overwritten in platform specific sections later on self._python_launcher = None self._python_arch = 'x86_64' self._python_implementation = platform.python_implementation() self._os_distro = platform.platform() # self._os_distro_short = platform.platform() self._win32api_installed = False self._windows_msys = False self._redhat_system = False self._debian_system = False self._suse_system = False self._pkg_fmt = None self._pkg_arch = None self._os_codename = 'unknown' self._os_arch = 'x86_64' self._os_version = (0, 0, 0) self._num_processors = multiprocessing.cpu_count() platform_system = platform.system().lower() self._platform_system = platform_system self._desktop_dir = None self._default_proj_home_dir = None if platform_system == 'linux': # e.g. x86_64 or i686 platform_machine = platform.machine().lower() if platform_machine != 'x86_64': assert re.match(r'i[6543]86', platform_machine, re.IGNORECASE) platform_machine = 'x86' self._os_arch = platform_machine self._python_arch = platform_machine # there's no portable way in python to obtain the linux version. self._query_linux_distro_info() if self.is_debian(): self._pkg_fmt = 'deb' self._pkg_arch = subprocess.check_output(['dpkg', '--print-architecture'], universal_newlines=True).rstrip() elif self.is_redhat() or self.is_suse(): self._pkg_fmt = 'rpm' self._pkg_arch = subprocess.check_output(['rpm', '--eval', '%_arch'], universal_newlines=True).rstrip() else: # unknown linux system, no logic available to figure out the package format or package architecture yet. self._pkg_fmt = 'unknown' self._pkg_arch = subprocess.check_output(['uname', '-m'], universal_newlines=True).rstrip() if self._pkg_arch == 'x86_64': self._pkg_arch = 'amd64' elif platform_system == 'windows': self._programx86_dir = None self._program_dir = None self._program_data_dir = None if 'MSYSTEM' in os.environ: self._windows_msys = True # obtain additional version information # windows 7: ('7', '6.1.7601', 'SP1', 'Multiprocessor Free') self._os_version = ver.version_tuple_from_str(platform.win32_ver()[1]) # Hm, win32api not installed/available -> system detection may not by accurate and includes some guessing. if platform.architecture()[0] != '64bit': self._python_arch = 'x86' self._os_arch = 'x86' if ('PROCESSOR_ARCHITEW6432' in os.environ) and (os.getenv('PROCESSOR_ARCHITEW6432') == 'AMD64'): # 32 bit python interpreter and 64 bit windows self._os_arch = 'x86_64' if self._os_arch == 'x86_64': if self._python_arch == 'x86': self._program_dir = os.path.normpath(os.getenv('PROGRAMW6432')) self._programx86_dir = os.path.normpath(os.getenv('PROGRAMFILES')) else: self._program_dir = os.path.normpath(os.getenv('PROGRAMFILES')) self._programx86_dir = os.path.normpath(os.getenv('PROGRAMFILES(X86)')) assert self._programx86_dir is not None elif self._os_arch == 'x86': self._program_dir = os.path.normpath(os.getenv('PROGRAMFILES')) else: assert False assert self._program_dir is not None self._program_data_dir = os.path.normpath(os.getenv('PROGRAMDATA')) if self._windows_msys: pass elif os.path.exists(os.path.join(r'C:\Windows', 'py.exe')): self._python_launcher = os.path.join(r'C:\Windows', 'py.exe') # probe the registry to ensure the shell will pass additional arguments to the # registered python interpreter. # if pywin_check: # self.check_pywin_registry() elif platform_system == 'darwin': # create a dictionary to simplify the mapping between minor version ID and codenames codename_dict = {'10.4': 'tiger', '10.5': 'leopard', '10.6': 'snow leopard', '10.7': 'lion', '10.8': 'mountain lion', '10.9': 'mavericks', '10.10': 'yosemite', '10.11': 'el capitan', '10.12': 'sierra', '10.13': 'high sierra', '10.14': 'mojave'} # replace darwin by macosx self._platform_system = 'macosx' # e.g. ('10.7.4', ('', '', ''), 'x86_64') mac_ver = platform.mac_ver() # save the macosx version as a tuple of integers self._os_version = ver.version_tuple_from_str(mac_ver[0]) # analyze the version tuple to derive the codename: lion, mountain lion, etc major_minor_ver = str(self._os_version[0]) + '.' + str(self._os_version[1]) if major_minor_ver in codename_dict: self._os_codename = codename_dict[major_minor_ver] #e.g. x86_64 self._os_arch = mac_ver[2] # python architecture is the same as the macosx architecture self._python_arch = self._os_arch else: raise Exception('unsupported platform detected: ' + platform_system) self._query_home_dir() self._query_default_proj_home_dir() self._query_desktop_dir() self._query_search_path() def get_python_version(self): return self._python_version def get_python_executable(self): return sys.executable def get_python_launcher(self): return self._python_launcher def is_python3(self): return ver.version_compare(self._python_version, (3, 0)) >= 0 def get_script_ext(self): if self.is_python3(): script_ext = '3.py' else: script_ext = '.py' return script_ext def get_python_implementation(self): return self._python_implementation def get_python_arch(self): return self._python_arch def get_platform(self): return self._platform_system def get_platform_long(self): return platform.platform() def is_linux(self): return self._platform_system == 'linux' def get_pkg_fmt(self): assert self._pkg_fmt is not None return self._pkg_fmt def get_pkg_arch(self): assert self._pkg_arch is not None return self._pkg_arch def is_redhat(self): return self._redhat_system def is_debian(self): return self._debian_system def is_suse(self): return self._suse_system def is_cray(self): if self._os_distro is None: return False return self._os_distro == 'cray' def is_windows(self): return self._platform_system == 'windows' def is_windows8(self): return self.is_windows() and (self._os_version[0] == 6) and (self._os_version[1] == 2) def is_windows_msys(self): return self._windows_msys def check_pywin_registry(self): assert self.is_windows() # Create a temporary script and invoke it to see whether argument passing works or not. # The test must go through the windows shell to be meaningful. tmp_dir = tempfile.mkdtemp() probe_script_name = os.path.join(tmp_dir, 'pywin_test.py') tmp_file = open(probe_script_name, "w") # create a simple script to echo the command arguments separated by a single space if self.is_python3(): tmp_file.write("#!/usr/bin/env python3\n") else: tmp_file.write("#!/usr/bin/env python\n") tmp_file.write("from __future__ import print_function\n") tmp_file.write("import sys\n") tmp_file.write("if len(sys.argv) > 1:\n") tmp_file.write(" joiner = ' '\n") tmp_file.write(" print(joiner.join(sys.argv[1:]))\n") tmp_file.close() # invoke the script through the windows shell and check the output retv = subprocess.check_output([probe_script_name, "probe"], shell=True, universal_newlines=True).rstrip() shutil.rmtree(tmp_dir) # print("check_pywin_registry: '" + retv + "'") if retv != "probe": msg = "\nThe python installation is broken, the shell does not pass on any command line arguments to the python script.\n" msg += "The following steps are most likely to fix the problem, for further assistance contact technical support.\n" msg += " - Deinstall all versions of python and reboot the system.\n" msg += " - Download the latest 64 bit version of python from www.python.org and install it, the build system will work with python 2.7.x or python 3.x.\n" raise Exception(msg) return True def check_os_detection(self, todo_list): if (self._os_version[0] == 0) and self.is_linux(): if not os.path.exists('/usr/bin/lsb_release'): todo_list.append("The system identification depends on lsb_release which does not seem to be available.") if self.is_redhat(): todo_list.append("On redhat 6.x/7.x and compatible systems, you may need to install redhat-lsb-core.") todo_list.append("") def is_macosx(self): return self._platform_system == 'macosx' def get_os_distro(self): return self._os_distro def get_os_distro_short(self): return self._os_distro def get_os_codename(self): return self._os_codename def get_os_arch(self): return self._os_arch def get_os_version(self): return self._os_version def get_number_processors(self): return self._num_processors def get_system_info_full_str(self): """Return a string consisting of colon separated fields intended for the Boost.Build script interface.""" str_list = [] str_list.append(self.get_platform()) str_list.append(self.get_os_arch()) str_list.append(str(self.get_number_processors())) # should be a single lowercase word as it may be used to make up a package filename str_list.append(self.get_os_distro_short()) str_list.append(self.get_os_codename()) # create a version string given the version tuple joiner = '.' str_list.append(joiner.join([str(x) for x in self.get_os_version()])) # no sure it's really needed somewhere in Boost.Build str_list.append(self._python_arch) if self.is_linux(): if self.is_debian(): str_list.append('debian') elif self.is_redhat(): str_list.append('redhat') elif self.is_suse(): str_list.append('suse') else: str_list.append('unknown_linux_flavor') else: str_list.append('none') str_list.append(self.get_home_dir()) return ';'.join(str_list) def get_path(self): return self._search_path def get_home_dir(self, native=False): if self.is_windows_msys() and native: home_dir = os.path.normpath(os.path.expandvars('$USERPROFILE')) else: home_dir = self._home_dir return home_dir def get_default_proj_home_dir(self): return self._default_proj_home_dir def get_desktop_dir(self): return self._desktop_dir def get_program_dir(self, target_arch): if not self.is_windows(): raise Exception("The method get_program_dir is only supported on the windows platform.") if (self.get_os_arch() == 'x86_64') and (target_arch == 'x86'): program_dir = self._programx86_dir else: program_dir = self._program_dir assert os.path.exists(program_dir) return program_dir def get_program_data_dir(self): return self._program_data_dir def get_short_path(self, fpath): if self.is_windows(): fpath = os.path.normpath(self.get_short_path_win(fpath)) return fpath def get_short_path_win(self, fpath): # need to go through the shell to get the short path name tempdir = tempfile.gettempdir() get_short_path_script = os.path.join(tempdir, 'pyhhi_get_short_path.cmd') if not os.path.exists(get_short_path_script): # create a shell command script to do the path conversion with open(get_short_path_script, "w") as script_file: script_file.write(textwrap.dedent("""\ @ECHO OFF echo %~s1 """)) # invoke the script through the windows shell. short_path = subprocess.check_output([get_short_path_script, fpath], shell=True, universal_newlines=True).rstrip() return short_path def check_comspec(self): comspec = os.getenv('COMSPEC') if (comspec is None) or (not os.path.exists(comspec)): raise Exception("The environment variable COMSPEC must be fixed, please contact technical support.") def get_subprocess_devnull(self): if ver.version_compare(self._python_version, (3,3)) >= 0: devnull = subprocess.DEVNULL else: self._logger.debug("attribute subprocess.DEVNULL not available (python < 3.3), using os.devnull instead") devnull = self._get_devnull() return devnull def _get_devnull(self): if not hasattr(self, '_devnull'): self._devnull = os.open(os.devnull, os.O_RDWR) return self._devnull def _query_linux_distro_info(self): if 'CRAYOS_VERSION' in os.environ: self._os_distro = 'cray' self._os_version = ver.version_tuple_from_str(os.environ['CRAYOS_VERSION']) else: lsb_release = '/usr/bin/lsb_release' if os.path.exists(lsb_release): # use lsb_release if available and assume all options are supported and return # sensible values. # obtain a human readable description of the distribution. This should be a single word as it # may be used to generate package filenames. retv = subprocess.check_output([lsb_release, '-is'], universal_newlines=True) self._os_distro = retv.rstrip().lower() retv = subprocess.check_output([lsb_release, '-rs'], universal_newlines=True) version_str = retv.rstrip() # version_str = "4" # version_str = "4.0-rolling" # version_str = "rolling" re_match = re.match(r'([0-9.,_-]+\d+)|(\d+)', version_str) if re_match: self._os_version = ver.version_tuple_from_str(re_match.group(0)) retv = subprocess.check_output([lsb_release, '-cs'], universal_newlines=True) self._os_codename = retv.rstrip().lower() if self._os_codename == 'n/a': self._os_codename = 'none' else: # lsb_release not found -> try to guess the distro but don't try to parse the # proprietary files to figure out the remaining system info bits. if os.path.exists('/etc/fedora-release'): self._os_distro = 'fedora' elif os.path.exists('/etc/redhat-release'): self._os_distro = 'redhat' elif os.path.exists('/etc/SuSE-release'): self._os_distro = 'suse' elif os.path.exists('/etc/debian_version'): self._os_distro = 'debian' else: self._os_distro = 'unknown' # make sure os_distro and os_codename do not contain any spaces as they may become part of a # package filename. if self._os_distro is not None: self._os_distro = self._os_distro.replace(' ', '-') if self._os_codename is not None: self._os_codename = self._os_codename.replace(' ', '-') # determine the general flavor of the linux system: redhat, debian or suse if os.path.exists('/etc/redhat-release'): self._redhat_system = True elif os.path.exists('/etc/debian_version'): self._debian_system = True else: # not sure how to do this for suse, revert back to regex if re.match(r'(suse)|(opensuse)', self._os_distro): self._suse_system = True def _query_home_dir(self): home_dir = os.path.expanduser('~') # make sure the user's home directory exists if not os.path.exists(home_dir): raise Exception('home directory "' + home_dir + '" does not exist.') self._home_dir = os.path.normpath(home_dir) def _query_default_proj_home_dir(self): if 'PROJ_HOME' in os.environ: proj_home_dir = os.path.normpath(os.path.expandvars('$PROJ_HOME')) else: proj_home_dir = os.path.join(self.get_home_dir(native=True), 'projects') if os.path.exists(proj_home_dir): self._default_proj_home_dir = proj_home_dir else: self._default_proj_home_dir = None def _query_search_path(self): self._search_path = [] env_path = os.getenv('PATH') for dir in env_path.split(os.path.pathsep): self._search_path.append(util.normalize_path(dir)) def _query_desktop_dir(self): # MSYS has its own environment but Desktop comes from the native windows home. home_dir = self.get_home_dir(native=True) desktop_dir = os.path.join(home_dir, 'Desktop') if os.path.exists(desktop_dir): self._desktop_dir = desktop_dir else: self._desktop_dir = None # the singleton as a class attribute instance = None def __init__(self, pywin_check=False): self._logger = logging.getLogger(__name__) if SystemInfo.instance is None: SystemInfo.instance = SystemInfo.__SystemInfo() if SystemInfo.instance.is_windows() and pywin_check: # The caller requested the additional windows registry check. # SystemInfo.instance.check_pywin_registry() # One more addtional check to catch a corrupted COMSPEC setting which yields to subsequent failures of # subprocess calls if shell=True is used. SystemInfo.instance.check_comspec() if SystemInfo.instance.get_os_arch() == 'x86': msg = "\nThe build system requires windows 64 bit but the platform seems to be windows 32 bit.\n" msg += "Please contact technical support for further assistance.\n" raise Exception(msg) elif (SystemInfo.instance.get_os_arch() == 'x86_64') and (SystemInfo.instance.get_python_arch() == 'x86'): msg = "\nPython 32 bit is not supported on windows 64 bit, please use python 64 bit." raise Exception(msg) def __getattr__(self, item): return getattr(SystemInfo.instance, item) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/util.py000077500000000000000000000250031442026013100230730ustar00rootroot00000000000000from __future__ import print_function import inspect import logging import os import platform import re import shutil import stat import subprocess import sys import traceback # imports a base exception with an attribute to enable or disable traceback information. from pyhhi.build.common.error import BaseError def exec_main_default_try(main_fnc, sys_exit_err=1, finally_action=None): """Execute main_fnc inside a try block and dump the callstack in case of exceptions.""" exit_error = False prog_name = os.path.basename(sys.argv[0]) try: main_fnc() # except (InvalidInputParameterError, InvalidCommandLineArgumentError) BaseError as e: except BaseError as e: exit_error = True if e.list_traceback: exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in lines[:-1]: print(line.rstrip()) print('-----') print("{0}: error: {1}".format(prog_name, e.msg)) except KeyboardInterrupt: exit_error = True #print("Keyboard interrupt signaled") except Exception: exit_error = True exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in lines[:-1]: print(line.rstrip()) print('-----') print(lines[-1]) finally: if finally_action: finally_action() if exit_error: # some exception thrown, exit with error code to inform the shell something went wrong. sys.exit(sys_exit_err) return 0 def app_args_add_log_level(parser): parser.add_argument("--log-level", action="store", dest="log_level", choices=['warning', 'info', 'debug'], default="warning", help="configure the log level [default: %(default)s]") def app_configure_logging(log_level): # assuming loglevel is bound to the string value obtained from the # command line argument. Convert to upper case to allow the user to # specify --log-level=DEBUG or --log-level=debug numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % log_level) # FORMAT = "py-trace %(module)s.%(funcName)s: %(lineno)d: %(message)s" FORMAT = "%(module)s.%(funcName)s: %(lineno)d: %(message)s" logging.basicConfig(format=FORMAT, level=numeric_level) def normalize_path(fpath): # remove leading and trailing spaces fpath = fpath.lstrip().rstrip() if platform.system().lower() == 'windows': # ensure drive letters are in uppercase which os.path.normpath() does not seem to enforce. re_drive_letter = re.compile(r'([a-z]):', re.IGNORECASE) re_match = re_drive_letter.match(fpath) if re_match: fpath = re_match.group(1).upper() + fpath[1:] return os.path.normpath(fpath) def to_posix_path(fpath): fpath = normalize_path(fpath) if platform.system().lower() == 'windows': fpath = fpath.replace('\\', '/') return fpath def find_tool_on_path(tool, must_succeed=False, search_path=None): """Find a tool on the search path and return the full path.""" if os.path.isabs(tool): if platform.system().lower() == 'windows': tool_basename = os.path.basename(tool) if not re.search(r'\.\S+$', tool_basename): tool = os.path.join(os.path.dirname(tool), tool_basename + '.exe') if os.path.exists(tool): return tool else: if platform.system().lower() == 'windows': # special fix for windows to qualify tool with .exe if tool does not have an extension. if not re.search(r'\.\S+$', tool): tool += '.exe' if search_path is None: search_path = os.path.expandvars('$PATH') search_path = search_path.split(os.path.pathsep) for d in search_path: if d == '.': continue prog = os.path.join(d, tool) if os.path.exists(prog) and (not os.path.isdir(prog)): # Always return an absolute path in case the current working directory will be changed later on. prog = os.path.abspath(prog) return prog if must_succeed: if os.path.isabs(tool): raise Exception("The command '" + tool + "' does not exist.") else: if search_path: raise Exception("The command " + tool + " cannot be found on PATH=" + ';'.join(search_path)) else: raise Exception("The command " + tool + " cannot be found on PATH.") return None def get_tool_dir(tool): if platform.system().lower() == 'windows': # some folks use slashes on windows or combination of slashes and backslashes re_pathsep = re.compile(r'[\\/:]+') else: # assume a linux path re_pathsep = re.compile(r'[/]+') if re_pathsep.search(tool): tool_path = normalize_path(os.path.abspath(tool)) else: tool_path = find_tool_on_path(tool) # Resolve any symbolic links to get the real location; e.g. # bjam.py is a symbolic link and points to $HOME/bin/bjam.py. The real location of bjam.py is writeable but # the location of the symbolic link may not. tool_path = os.path.realpath(tool_path) tool_dir = os.path.dirname(tool_path) return tool_dir def get_top_dir(): # 1st check: try current working directory top_dir = os.getcwd() if is_top_dir(top_dir): return top_dir # 2nd check: try to deduce top from the script directory; e.g. /CMakeBuild/bin or /BoostBuild/bin top_dir = os.path.normpath(os.path.join(get_script_dir(), '..', '..')) if not is_top_dir(top_dir): raise Exception(os.path.basename(sys.argv[0]) + " failed to find its parent workspace, please contact technical support.") return top_dir def is_top_dir(top_dir): if not os.path.exists(top_dir): return False # Path check returns true if CMakeBuild is a top-level SVN external or Git submodule. if not os.path.exists(os.path.join(top_dir, 'CMakeBuild')): return False if os.path.exists(os.path.join(top_dir, 'CMakeBuild', 'bin', 'cmake.py')) or os.path.exists(os.path.join(top_dir, 'CMakeBuild', 'CMakeBuild', 'bin', 'cmake.py')): return True # Check for CMakeBuild versioned subtree cmakebuild_dir = os.path.join(top_dir, 'CMakeBuild') for fname in os.listdir(cmakebuild_dir): if os.path.isdir(os.path.join(cmakebuild_dir, fname)): if os.path.exists(os.path.join(cmakebuild_dir, fname, 'CMakeBuild', 'bin', 'cmake.py')): return True return False def get_script_dir(): py_util_fname = inspect.getfile(get_script_dir) # /CMakeBuild/bin/pyhhi/build/common/util.py script_dir = os.path.normpath(os.path.join(os.path.dirname(py_util_fname), '..', '..', '..')) return script_dir def get_boost_build_dir(top_dir): # Assume the standard SVN layout without a submodules folder holding the externals. boost_build_dir = os.path.join(top_dir, 'BoostBuild') if not os.path.exists(boost_build_dir): raise Exception("The directory '" + top_dir + "' does not seem to be a workspace directory with a BoostBuild folder, please contact technical support.") return boost_build_dir def find_repo_path_from_src_path(src_path): src_path = os.path.abspath(src_path.rstrip(os.path.sep)) is_windows = platform.system().lower() == 'windows' # split the path if is_windows: drive_path_comps = os.path.splitdrive(src_path) src_path = drive_path_comps[1] dir_list = src_path.lstrip(os.path.sep).split(os.path.sep) joiner = os.path.sep while dir_list: # walk the tree until 'src' is found. The parent of src is supposed to be the name of the repository. dir = dir_list.pop() if len(dir_list) < 2: break if dir.lower() == 'src': if is_windows: jamroot_dir = os.path.join(drive_path_comps[0], os.path.sep, joiner.join(dir_list[:-1])) repo_path = os.path.join(drive_path_comps[0], os.path.sep, joiner.join(dir_list)) else: # repo_path: /home/rauthenberg/projects/BoostBuild/BoostBuild jamroot_dir = os.path.join(os.path.sep, joiner.join(dir_list[:-1])) repo_path = os.path.join(os.path.sep, joiner.join(dir_list)) if os.path.isfile(os.path.join(jamroot_dir, 'Jamroot')): return repo_path raise Exception("The repository path cannot be deduced from '" + src_path + "'") def find_repo_name_from_src_path(src_path): repo_path = find_repo_path_from_src_path(src_path) if platform.system().lower() == 'windows': drive_path_comps = os.path.splitdrive(repo_path) repo_path = drive_path_comps[1] return repo_path.lstrip(os.path.sep).split(os.path.sep)[-1] def subproc_call_flushed(*popenargs, **kwargs): """Run command with arguments. Wait for command to complete or timeout, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) """ sys.stdout.flush() return subprocess.call(*popenargs, **kwargs) def subproc_check_call_flushed(*popenargs, **kwargs): """Run command with arguments. Wait for command to complete. If the exit code was zero then return, otherwise raise CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute. The arguments are the same as for the call function. Example: check_call(["ls", "-l"]) """ sys.stdout.flush() return subprocess.check_call(*popenargs, **kwargs) def rmtree(directory): """On Windows invokes rmtree_readonly() and on other platforms shutil.rmtree(). This convenience function may be used as an replacement of shutil.rmtree(directory) to be able to remove directory trees on Windows containing some readonly files. """ if sys.platform.startswith('win'): rmtree_readonly(directory) else: shutil.rmtree(directory) def rmtree_readonly(directory): """Remove a directory tree on Windows where some files are readonly.""" def remove_readonly(func, path, _excinfo): "Clear the readonly bit and reattempt the removal" os.chmod(path, stat.S_IWRITE) func(path) shutil.rmtree(directory, onerror=remove_readonly) HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/common/ver.py000077500000000000000000000212441442026013100227150ustar00rootroot00000000000000 from __future__ import print_function import platform import re import os.path import plistlib import subprocess import functools import pyhhi.build.common.util as util import pyhhi.build.common.cmbldver as cmbldver def get_cmake_build_version(): return version_tuple_from_str(cmbldver.CMAKE_BUILD_VERSION_STR) def _get_python_version_numeric(): re_number = re.compile(r'(\d+).*') version_list = [] # extra logic to deal with python on ubuntu 11.10: 2.7.2+ for x in platform.python_version_tuple(): re_match = re_number.match(x) if re_match: version_list.append(int(re_match.group(1), 10)) else: version_list.append(0) return tuple(version_list) def check_python_version(version_tuple=None): """Checks the python version and throws an exception if the version is not supported.""" if version_tuple is None: version_tuple = _get_python_version_numeric() if version_compare(version_tuple, (2, 7)) < 0: raise Exception('python ' + platform.python_version() + ' is not supported. Please update to 2.7 or higher.') def get_python_version(check_version=False): version_tuple = _get_python_version_numeric() if check_version: check_python_version(version_tuple) return version_tuple def version_tuple_from_str(version, nelem=None): """Split a version string using '.' and '-' as separators and return a tuple of integers.""" re_match = re.match(r'([0-9.,_-]+\d+)|(\d+)', version) if re_match: version_list = re.split('[.,_-]', re_match.group(0)) if nelem is not None: # adjust the list to contain exactly the specified number of elements. while len(version_list) < nelem: version_list.append('0') return tuple([int(x, 10) for x in version_list[:nelem]]) else: return tuple([int(x, 10) for x in version_list]) else: raise Exception("The version string '" + version + "' is not supported, no leading numeric digits found.") def get_boost_version_str(version_str): re_match = re.match(r'([0-9.]+\d+)', version_str) if not re_match: raise Exception("The version string '" + version_str + "' cannot be converted into a boost compliant version string.") boost_version_str = re.sub(r'\.', '_', re_match.group(1)) return boost_version_str def version_tuple_to_str(version, sep='.'): """Join the version components using '.' and return the string.""" return sep.join([str(x) for x in version]) def version_list_to_str(version_list): return ' '.join([version_tuple_to_str(x) for x in version_list]) def ubuntu_version_tuple_to_str(version): """Join the first two version components of an ubuntu release number and return the string.""" assert len(version) >= 2 version_str = '%d.%02d' % (version[0], version[1]) return version_str def version_compare(version1, version2): """Compare two version iterables consisting of arbitrary number of numeric elements.""" len_version1 = len(version1) len_version2 = len(version2) if len_version1 == len_version2: # Both version objects have the same number of components, compare them left to right for i in range(len_version1): if version1[i] > version2[i]: return 1 elif version1[i] < version2[i]: return -1 # version objects compare equal return 0 elif len_version1 > len_version2: version2_tmp = list(version2) while len(version2_tmp) < len_version1: version2_tmp.append(0) return version_compare(version1, version2_tmp) else: version1_tmp = list(version1) while len(version1_tmp) < len_version2: version1_tmp.append(0) return version_compare(version1_tmp, version2) def version_list_sort(version_list): # Written for Python 2.7 and 3.x: functools.cmp_to_key() requires 2.7 or higher. # Notes: python 2.x supports a second argument cmp to specify the comparision function but # python 3.x does not. return sorted(version_list, key=functools.cmp_to_key(version_compare)) def version_str_to_rpm_version_tuple(version): re_match = re.match(r'([^-]+)-(\S+)', version) if re_match: return re_match.group(1), re_match.group(2) else: re_match = re.match(r'([\d.-]+)[-.](\d+)', version) if re_match: return re_match.group(1), re_match.group(2) raise Exception("The version string '" + version + "' is not a valid RPM version string.") def get_default_version_filename(src_filename): """Returns the default version filename given a source filename.""" repo_name = util.find_repo_name_from_src_path(src_filename) repo_path = util.find_repo_path_from_src_path(src_filename) return os.path.join(repo_path, 'include', repo_name, 'version.h') def parse_version_file(version_file, verbatim=False): """Parse standard version file and return the version ID as a numeric tuple or verbatim.""" if not os.path.exists(version_file): raise Exception("version file '" + version_file + "' does not exist.") # look at the extension to determine the file type: header file or plist file. (root, ext) = os.path.splitext(version_file) if ext == '.plist': return _parse_version_plist_file(version_file, verbatim) else: return _parse_version_h_file(version_file, verbatim) def _parse_version_h_file(version_file, verbatim=False): """Parse standard version file and return the version ID as a numeric tuple or verbatim.""" if not os.path.exists(version_file): raise Exception("version file '" + version_file + "' does not exist.") re_version_expr = re.compile(r'(^#if\s+![ ]*defined\(.*)|(^#\s*define\s+\S+_VERSION\s+)') re_version_tag_expr = re.compile(r'^#if\s+!\s*defined\(\s*([a-zA-Z0-9_]+)\s*\)') version_tag = None with open(version_file) as f: for line in f: re_match = re_version_expr.match(line) if not re_match: continue # print("version.h: found cpp line: {}".format(line)) if version_tag is None: re_match = re_version_tag_expr.match(line) if re_match: version_tag = re_match.group(1) # print("found version tag: {}".format(version_tag)) re_version_str = re.compile(r'^#define\s+{}\s+"([^"]+)'.format(version_tag)) re_version_str2 = re.compile(r'^#define\s+{}\s+(\d+)'.format(version_tag)) continue else: # print("checking cpp line: {}".format(line)) # version tag found re_match = re_version_str.match(line) if not re_match: re_match = re_version_str2.match(line) if re_match: if verbatim: return re_match.group(1) else: return version_tuple_from_str(re_match.group(1)) raise Exception("No version ID found in file '" + version_file + "'.") def _parse_version_plist_file(plist_file, verbatim=False): """Parse Info.plist file and return the version ID as a numeric tuple or verbatim.""" if not os.path.exists(plist_file): raise Exception("version file '" + plist_file + "' does not exist.") version_str = None if (platform.system().lower() == 'darwin') and _is_binary_plist_file(plist_file): # On MacOSX there are two different plist formats supported: the older xml format and on more recent releases # the binary format. The latter is not supported by Python's plistlib directly. retv = subprocess.check_output(['/usr/bin/plutil', '-convert', 'xml1', '-o', '-', plist_file], universal_newlines=True) pl_dict = plistlib.readPlistFromString(retv) else: pl_dict = plistlib.readPlist(plist_file) # An Info.plist file is expected to contain at least one of the following version keys: CFBundleVersion and CFBundleShortVersionString. if 'CFBundleShortVersionString' in pl_dict: version_str = pl_dict['CFBundleShortVersionString'] elif 'CFBundleVersion' in pl_dict: version_str = pl_dict['CFBundleVersion'] else: raise Exception("No version ID found in file '" + plist_file + "'.") if verbatim: return version_str else: return version_tuple_from_str(version_str) def _is_binary_plist_file(plist_file): if not os.path.exists(plist_file): raise Exception("file '" + plist_file + "' does not exist.") retv = subprocess.check_output(['/usr/bin/file', plist_file], universal_newlines=True) if re.search('binary property list', retv): return True else: return False HM-HM-18.0/cmake/CMakeBuild/bin/pyhhi/build/vcsutil.py000077500000000000000000001066201442026013100223240ustar00rootroot00000000000000 from __future__ import print_function import logging import os import posixpath import re import shutil import subprocess import sys import tempfile import pyhhi.build.common.ver as ver import pyhhi.build.common.util as util from pyhhi.build.common.system import SystemInfo class VcsCommandTracer(object): def __init__(self, enable_command_history=True): self._logger = logging.getLogger(__name__) if self._logger.isEnabledFor(logging.DEBUG): self._verbosity_level = 1 else: self._verbosity_level = 0 self._prog_name = os.path.basename(sys.argv[0]) self._command_history = [] self._enable_command_history = enable_command_history def add_to_command_history(self, cmd_argv): if self._enable_command_history: self._command_history.append(' '.join(cmd_argv)) def get_command_history(self): return self._command_history def clear_command_history(self): self._command_history = [] def trace_command(self, cmd_argv): if self._verbosity_level > 0: print("Launching: %s" % ' '.join(cmd_argv)) self.add_to_command_history(cmd_argv) class VcsUrl(object): def __init__(self, url_str=None): self._sys_info = SystemInfo() self._proto = None self._username = None self._host = None self._resource_path = None self._re_scp_url = re.compile(r'^([^@/\\:]+)@([^:]+):([^/].+)$') if url_str: (self._proto, self._username, self._host, self._resource_path) = self.parse_from_string(url_str) def get_protocol(self): return self._proto def get_hostname(self): return self._host def get_username(self): return self._username def get_resource_path(self, native=False): if self._resource_path: if native and (self._proto is not None) and (self._proto == 'file') and self._sys_info.is_windows(): # Convert the resource path to a native file system path. if self._resource_path.startswith('/'): assert len(self._resource_path) > 1 return os.path.normpath(self._resource_path[1:]) elif re.match(r'^[a-zA-Z]:', self._resource_path): assert len(self._resource_path) > 2 return os.path.normpath(self._resource_path) return self._resource_path def set_resource_path(self, res_path): self._resource_path = res_path def parse_from_string(self, url_str): proto = None username = None host = None resource_path = None re_match = self._re_scp_url.match(url_str) if re_match: # Split scp URL proto = 'ssh' username = re_match.group(1) host = re_match.group(2) resource_path = re_match.group(3) else: # Check for proto:// re_match = re.match(r'^([a-z][^:/]+)://(.+)$', url_str) if re_match: proto = re_match.group(1) if proto == 'file': # A relative path will be converted into an absolute path. resource_path = re_match.group(2) if self._sys_info.is_windows(): fs_path_native = os.path.abspath(os.path.normpath(resource_path)) resource_path = util.to_posix_path(fs_path_native) else: resource_path = os.path.abspath(resource_path) else: host_res_path = re_match.group(2) re_match = re.match(r'^([^/]+)/(.+)$', host_res_path) if re_match: host_part = re_match.group(1) host = host_part resource_path = re_match.group(2) if proto == 'ssh': # Analyze the host_part re_match = re.match(r'([^@]+)@([^@]+)$', host_part) if re_match: username = re_match.group(1) host = re_match.group(2) else: # Unsupported URL raise Exception("Unsupported URL: {0}".format(url_str)) else: # Assume a native file system path. proto = 'file' fpath_abs = os.path.abspath(url_str) # On windows backslashes are converted to slashes. resource_path = util.to_posix_path(fpath_abs) self._proto = proto self._username = username self._host = host if resource_path is None: self._resource_path = resource_path else: if proto != 'file': # Windows file URLs start with a driver letter and are not supported by posixpath. # Example file://C:/Users/user -> resource path C:/Users/user. resource_path = posixpath.normpath(resource_path) self._resource_path = resource_path return proto, username, host, resource_path def __str__(self): if self._proto == 'file': s = "{0}://{1}".format(self._proto, self._resource_path) elif (self._proto == 'ssh') and (self._username is not None): s = "{0}://{1}@{2}/{3}".format(self._proto, self._username, self._host, self._resource_path) else: s = "{0}://{1}/{2}".format(self._proto, self._host, self._resource_path) return s class VcsUtil(object): def __init__(self, cmd_tracer=None): self._logger = logging.getLogger(__name__) self._sys_info = SystemInfo() self._remove_tmp_files = True if self._logger.isEnabledFor(logging.DEBUG): self._remove_tmp_files = False self._re_empty_line = re.compile(r'^\s*$') self._prog_name = os.path.basename(sys.argv[0]) if cmd_tracer is None: self._cmd_tracer = VcsCommandTracer() else: self._cmd_tracer = cmd_tracer def get_subprocess_devnull(self): return self._sys_info.get_subprocess_devnull() def strip_empty_comment_lines(self, comment_lines): """Strip empty lines at the beginning and from the end of comment lines passed and return them.""" if not comment_lines: return comment_lines while len(comment_lines) > 0: if self._re_empty_line.match(comment_lines[0]): comment_lines.pop(0) else: break while len(comment_lines) > 0: if self._re_empty_line.match(comment_lines[-1]): comment_lines.pop() else: break return comment_lines def save_comment_lines_tmpf(self, comment_lines, add_final_newline=True): assert len(comment_lines) > 0 (tmp_fh, tmp_fname) = tempfile.mkstemp(text=True) tmp_file = os.fdopen(tmp_fh, 'w') tmp_file.write('\n'.join(comment_lines)) if add_final_newline: # and one newline to terminate the last line. tmp_file.write('\n') tmp_file.close() return tmp_fname def remove_tmp_file(self, fname): if not os.path.exists(fname): return if self._remove_tmp_files: os.remove(fname) else: print("Keeping temporary file: ", fname) class GitHelper(VcsUtil): def __init__(self, cmd_tracer=None): VcsUtil.__init__(self, cmd_tracer) self._logger = logging.getLogger(__name__) # git-svn-id: https://visvn.fe.hhi.de/svn/svn_CMakeBuild/tags/3.11.2-1@791 a315372b-2729-4e68-a986-494f0c48443b self._re_svn_import_id = re.compile(r'^(git-svn-id|svntogit-id):\s*([^@]+)@([0-9]+)\s+(\S+)') # Attribute _git_executable reserved for future extensions. self._git_executable = util.find_tool_on_path('git', must_succeed=True) self._git_version = self._discover_git_version() def _discover_git_version(self): git_argv = [self._git_executable, '--version'] retv = subprocess.check_output(git_argv, universal_newlines=True) lines = retv.splitlines() re_match = re.search(r'[0-9.]+\.\d+', lines[0]) if re_match: git_version = ver.version_tuple_from_str(re_match.group(0)) return git_version else: raise Exception("git --version returned: '{0}' - version expression not understood.".format(retv)) def get_git_executable(self): return self._git_executable def get_git_version(self): return self._git_version def get_command_history(self): return self._cmd_tracer.get_command_history() def clear_command_history(self): self._cmd_tracer.clear_command_history() def is_empty_repo(self, repo_dir=None): git_argv = [self._git_executable, 'show-ref', '-q'] # Save initial current working directory cur_dir = os.getcwd() if repo_dir is None: assert os.path.exists(os.path.join(cur_dir, '.git')) self.trace_git_command(git_argv) retv = util.subproc_call_flushed(git_argv) else: assert os.path.exists(os.path.join(repo_dir, '.git')) os.chdir(repo_dir) self.trace_git_command(git_argv) retv = util.subproc_call_flushed(git_argv) # Recover initial current working directory os.chdir(cur_dir) return retv != 0 def get_local_branches(self): local_branches = [] git_argv = [self._git_executable, 'branch'] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) re_expr = re.compile(r'^\*?\s+(\S+)') for line in retv.splitlines(): l = line.rstrip() re_match = re_expr.match(l) if re_match: local_branches.append(re_match.group(1)) return local_branches def get_remote_branches(self, repo='origin'): remote_branches = [] git_argv = [self._git_executable, 'ls-remote', '--heads', repo] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) re_expr = re.compile(r'\S+\s+refs/heads/(\S+)') for line in retv.splitlines(): l = line.rstrip().lstrip() re_match = re_expr.match(l) if re_match: remote_branches.append(re_match.group(1)) return remote_branches def get_local_tags(self): local_tags = [] git_argv = [self._git_executable, 'tag'] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) for line in retv.splitlines(): l = line.rstrip().lstrip() if re.match(r'^\S+', l): local_tags.append(l) return local_tags def get_remote_tags(self, repo='origin'): remote_tags = [] git_argv = [self._git_executable, 'ls-remote', '--tags', '--refs', repo] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) # 5acba4bba0159c921d3e9de82a450d0e48092d1f refs/tags/3.10.1-1 re_expr = re.compile(r'\S+\s+refs/tags/(\S+)') for line in retv.splitlines(): l = line.rstrip().lstrip() re_match = re_expr.match(l) if re_match: remote_tags.append(re_match.group(1)) return remote_tags def get_submodule_paths(self): submd_paths = [] if not os.path.exists('.gitmodules'): # If .gitmodules does not exist, we don't have any submodules. # If it does exist, we may have some provided the file is not empty. return submd_paths elif os.stat('.gitmodules').st_size == 0: # Check for empty .gitmodules return submd_paths if ver.version_compare(self._git_version, (2, 7)) < 0: raise Exception("git version {0} is too old, please update to 2.7 or higher".format(ver.version_tuple_to_str(self._git_version))) git_argv = [self._git_executable, 'submodule--helper', 'list'] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) for line in retv.splitlines(): if self._re_empty_line.match(line): continue l = line.rstrip().lstrip() fields = l.split() if fields: self._logger.debug("found submodule path {0}".format(fields[-1])) submd_paths.append(fields[-1]) return submd_paths def get_tag_log(self, tag, strip_git_svn_id=False, strip_empty_lines=True): tag_log = [] git_argv = [self._git_executable, 'tag', '-l', '--format=%(contents)', tag] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) log_lines = retv.splitlines() for line in log_lines: if strip_git_svn_id and (line.startswith('git-svn-id:') or line.startswith('svntogit-id:')): continue tag_log.append(line) if strip_empty_lines: tag_log = self.strip_empty_comment_lines(tag_log) return tag_log def get_commit_hash(self, tag=None): git_argv = [self._git_executable, 'rev-list', '-n', '1'] if tag is None: git_argv.append('HEAD') else: git_argv.append(tag) self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) return retv.lstrip().rstrip() def parse_svn_import_id(self, comment_lines): for line in comment_lines: re_match = self._re_svn_import_id.match(line) if re_match: svn_url = re_match.group(2) svn_rev = int(re_match.group(3)) svn_repo_uuid = re_match.group(4) return svn_url, svn_rev, svn_repo_uuid return None def get_wc_commit_log(self, strip_git_svn_id=True, strip_empty_lines=True): commit_log = [] # List commit message preserving newlines. git_argv = [self._git_executable, 'log', '--pretty=tformat:%B', '-n', '1'] self.trace_git_command(git_argv) retv = subprocess.check_output(git_argv, universal_newlines=True) log_lines = retv.splitlines() for line in log_lines: if strip_git_svn_id and line.startswith('git-svn-id:'): continue commit_log.append(line) if strip_empty_lines: # Strip leading and trailing empty lines commit_log = self.strip_empty_comment_lines(commit_log) return commit_log def trace_git_command(self, git_argv): self._cmd_tracer.trace_command(git_argv) def get_latest_cmakebuild_tag(self, cmakebuild_repo): cmakebuild_tags = self.get_remote_tags(cmakebuild_repo) cmakebuild_version_list = [] cmakebuild_release_tag_map = {} re_expr_release_tag = re.compile(r'^[0-9.-]+$') for tag in cmakebuild_tags: if re_expr_release_tag.match(tag): # Release tag found cmakebuild_version = ver.version_tuple_from_str(tag) cmakebuild_version_list.append(cmakebuild_version) cmakebuild_version_str = ver.version_tuple_to_str(cmakebuild_version) # Adds a mapping from a normalized version string to the tag: e.g. 3.12.3.4 -> 3.12.3-4 cmakebuild_release_tag_map[cmakebuild_version_str] = tag else: self._logger.info("ignoring CMakeBuild tag {} - it does not match the release pattern.".format(tag)) if not cmakebuild_version_list: raise Exception("No CMakeBuild release tag found.") cmakebuild_version_list = ver.version_list_sort(cmakebuild_version_list) cmakebuild_version = cmakebuild_version_list[-1] cmakebuild_tag = cmakebuild_release_tag_map[ver.version_tuple_to_str(cmakebuild_version)] self._logger.info("selecting CMakeBuild tag {}".format(cmakebuild_tag)) return cmakebuild_tag class SvnProperties(object): def __init__(self): self._svn_prop_list = [] # key = svn property, value = list of property values self._svn_prop_value_dict = {} def is_empty(self): return len(self._svn_prop_list) == 0 def clear(self): self._svn_prop_list = [] self._svn_prop_value_dict = {} def add_property(self, prop, prop_values): # Each property must have at least one associated value. assert len(prop_values) >= 1 self._svn_prop_list.append(prop) self._svn_prop_value_dict[prop] = prop_values def update_property(self, prop, prop_values): # Each property must have at least one associated value. assert len(prop_values) >= 1 assert self.has_property(prop) self._svn_prop_value_dict[prop] = prop_values def get_property_list(self): return self._svn_prop_list def has_property(self, prop): if prop in self._svn_prop_value_dict: return True else: return False def get_property(self, prop): return self._svn_prop_value_dict[prop] def remove_property(self, prop): if not self.has_property(prop): return self._svn_prop_list.remove(prop) self._svn_prop_value_dict.pop(prop) def __str__(self): if self.is_empty(): return '' lines = [] for prop in self._svn_prop_list: # lines.append("{0:>2}{1}".format(' ', prop)) lines.append(prop) for prop_value in self._svn_prop_value_dict[prop]: # lines.append("{0:>4}{1}".format(' ', prop_value)) lines.append("{0:>2}{1}".format(' ', prop_value)) # SVN seems to be in favor of a newline terminating multivalue properties if len(self._svn_prop_value_dict[prop]) > 1: lines.append('\n') # Serialize svn properties into a single string and avoid a duplicate newline after # a multivalue property; e.g. props_str = '' for ln in lines: if ln != '\n': props_str += "{}\n".format(ln) else: # a newline value must not be duplicated. props_str += ln return props_str class SvnPropFileParser(object): def __init__(self): self._logger = logging.getLogger(__name__) def parse_property_file(self, filenm): if not os.path.exists(filenm): raise Exception("SVN property file {0} does not exist.".format(filenm)) svn_prop_lines = [] with open(filenm) as svnpropf: for line in svnpropf: l = line.rstrip() svn_prop_lines.append(l) svn_prop = self.parse_property_file_content(svn_prop_lines) return svn_prop def parse_gitignore_file(self, filenm): if not os.path.exists(filenm): raise Exception("gitignore file {0} does not exist.".format(filenm)) gitignore_lines = [] with open(filenm) as svnpropf: for line in svnpropf: l = line.rstrip() gitignore_lines.append(l) svn_prop = self.parse_gitignore_file_content(gitignore_lines) return svn_prop def parse_property_file_content(self, svn_prop_lines): svn_prop = SvnProperties() prop_name = None prop_value_list = [] re_prop_name = re.compile(r'^(\s*)(\S+)') re_discard_line = re.compile(r'(^\s*$)|(^#.*$)|(^Properties on.*$)') line_cnt = 1 while len(svn_prop_lines) > 0: line = svn_prop_lines[0] if not re_discard_line.match(line): # print(line) if prop_name is None: # This line is supposed to contain a property like svn:ignore, leading ws is supported. re_match = re_prop_name.match(line) if re_match: leading_ws_prop_name = re_match.group(1) prop_name = re_match.group(2) prop_value_list = [] else: raise Exception("SVN property parsing error at line {0:d}: {1}".format(line_cnt, line)) else: # Next property value or next property name? if line.startswith(' ' + leading_ws_prop_name): prop_value = line.lstrip() prop_value_list.append(prop_value) else: if prop_value_list: svn_prop.add_property(prop_name, prop_value_list) else: self._logger.debug("ignoring empty SVN property: {0}".format(prop_name)) # print("new property: {0} -> {1}".format(prop_name, ' '.join(prop_value_list))) prop_name = None prop_value_list = [] # This line must be reparsed, it's the next property. continue else: self._logger.debug("ignoring line: {0}".format(line)) svn_prop_lines.pop(0) line_cnt = line_cnt + 1 if prop_name is not None: if prop_value_list: svn_prop.add_property(prop_name, prop_value_list) # print("new property: {0} -> {1}".format(prop_name, ' '.join(prop_value_list))) #if not svn_prop.is_empty(): # print(svn_prop) return svn_prop def parse_gitignore_file_content(self, gitignore_lines, svn_prop=None): svn_ignores = [] re_discard_line = re.compile(r'(^\s*$)|(^#.*$)') re_top_folder = re.compile(r'^/([^/]+)/$') re_folder = re.compile(r'^([^/]+)/$') for line in gitignore_lines: if re_discard_line.match(line): continue ln_trimmed = line.lstrip().rstrip() if '/' in ln_trimmed: re_match = re_top_folder.match(ln_trimmed) if re_match: svn_ignores.append(re_match.group(1)) continue re_match = re_folder.match(ln_trimmed) if re_match: svn_ignores.append(re_match.group(1)) continue else: svn_ignores.append(ln_trimmed) if svn_ignores: if svn_prop is None: svn_prop = SvnProperties() svn_prop.add_property('svn:ignore', svn_ignores) return svn_prop class SvnHelper(VcsUtil): def __init__(self, cmd_tracer=None): VcsUtil.__init__(self, cmd_tracer) self._logger = logging.getLogger(__name__) self._dry_run = False self._svn_repo_std_layout = True # Not really useful right now but added for future extensions to deal with platforms # which don't have svn on the search path (e.g. windows or macOS). self._svn_executable = util.find_tool_on_path('svn', must_succeed=True) self._svnadmin_executable = self._find_svnadmin() self._svnmucc_executable = self._find_svnmucc() def _find_svnadmin(self): if os.path.isabs(self._svn_executable): svn_prog = self._svn_executable else: svn_prog = util.find_tool_on_path('svn', must_succeed=True) svn_dir = os.path.dirname(svn_prog) if self._sys_info.is_windows(): svnadmin = os.path.join(svn_dir, 'svnadmin.{0}'.format('exe')) else: svnadmin = os.path.join(svn_dir, 'svnadmin') return svnadmin def _find_svnmucc(self): if os.path.isabs(self._svn_executable): svn_prog = self._svn_executable else: svn_prog = util.find_tool_on_path('svn', must_succeed=True) svn_dir = os.path.dirname(svn_prog) if self._sys_info.is_windows(): svnmucc = os.path.join(svn_dir, 'svnmucc.{0}'.format('exe')) else: svnmucc = os.path.join(svn_dir, 'svnmucc') if not os.path.exists(svnmucc): svnmucc = None return svnmucc def set_dry_run(self, dry_run=True): self._dry_run = dry_run def get_svn_executable(self): return self._svn_executable def get_svnadmin_executable(self): return self._svnadmin_executable def create_empty_repository(self, repo_path, std_layout=True): repo_path = os.path.normpath(os.path.abspath(repo_path)) if os.path.exists(repo_path): raise Exception("SVN repository path {} already exists.".format(repo_path)) repo_dir = os.path.dirname(repo_path) if not os.path.exists(repo_dir): os.makedirs(repo_dir) svn_argv = [self._svnadmin_executable, 'create', repo_path] self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) if std_layout: svn_repo_path_posix = util.to_posix_path(repo_path) for pth in ['trunk', 'branches', 'tags']: svn_url = "file://{0}/{1}".format(svn_repo_path_posix, pth) svn_argv = [self._svn_executable, 'mkdir', '-m', 'creating folder {}'.format(pth), svn_url] self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) def has_svnmucc(self): return self._svnmucc_executable is not None def get_svnmucc_executable(self): return self._svn_executable def get_command_history(self): return self._cmd_tracer.get_command_history() def clear_command_history(self): self._cmd_tracer.clear_command_history() def get_tag_url(self, svn_repo, tag): assert self._svn_repo_std_layout return "{0}/tags/{1}".format(svn_repo, tag) def get_branch_url(self, svn_repo, branch): assert self._svn_repo_std_layout if branch == 'trunk': return "{0}/{1}".format(svn_repo, branch) else: return "{0}/branches/{1}".format(svn_repo, branch) def get_tags(self, svn_repo, with_rev=False): tags = self.get_svn_folders(svn_repo + '/tags', with_rev) return tags def get_latest_tag(self, svn_repo): tags = self.get_tags(svn_repo) if not tags: return None tag_rev_list = [] for tag in tags: svn_tag_url = self.get_tag_url(svn_repo, tag) tag_rev = self.get_svn_rev(svn_tag_url) tag_rev_list.append(tuple([tag, tag_rev])) # Sort by revision tag_rev_list = sorted(tag_rev_list, key=lambda tag_rev: tag_rev[1]) (latest_tag, tag_rev) = tag_rev_list[-1] return latest_tag def get_branches(self, svn_repo, with_rev=False): branches = self.get_svn_folders(svn_repo + '/branches', with_rev) return branches def get_svn_folders(self, svn_url, with_rev=False): svn_folders = [] svn_argv = [self._svn_executable, 'list', svn_url] self.trace_svn_command(svn_argv) retv = subprocess.check_output(svn_argv, universal_newlines=True) re_trailing_slash = re.compile(r'^(.+)/$') for line in retv.splitlines(): l = line.rstrip().lstrip() re_match = re_trailing_slash.match(l) if re_match: svn_folder = re_match.group(1) if with_rev: rev = self.get_svn_rev("{0}/{1}".format(svn_url, svn_folder)) svn_folder += "@{0:d}".format(rev) svn_folders.append(svn_folder) return svn_folders def get_svn_rev(self, svn_url): svn_argv = [self._svn_executable, 'info', '--show-item', 'last-changed-revision', svn_url] self.trace_svn_command(svn_argv) retv = subprocess.check_output(svn_argv, universal_newlines=True) retv = retv.rstrip() rev = int(retv) return rev def get_repo_uuid(self, svn_repo): svn_argv = [self._svn_executable, 'info', '--show-item', 'repos-uuid', svn_repo] self.trace_svn_command(svn_argv) retv = subprocess.check_output(svn_argv, universal_newlines=True) retv = retv.lstrip().rstrip() return retv def get_svn_log_msg(self, svn_url): # svn log -l 1 https://visvn.fe.hhi.de/svn/svn_CMakeBuild/tags/3.11.0-1 svn_argv = [self._svn_executable, 'log', '-l', '1', svn_url] self.trace_svn_command(svn_argv) retv = subprocess.check_output(svn_argv, universal_newlines=True) comment_lines = retv.splitlines() assert len(comment_lines) >= 3 assert comment_lines[0].startswith('---') comment_lines.pop(0) # Drop rXXXX ... comment_lines.pop(0) assert comment_lines[-1].startswith('---') comment_lines.pop() comment_lines = self.strip_empty_comment_lines(comment_lines) return comment_lines def svn_save_property_values_tmpf(self, prop_values): tmp_fname = self.save_comment_lines_tmpf(prop_values) return tmp_fname def svn_save_properties(self, svn_props, fname, header_lines=None): svn_props_serialized = str(svn_props) with open(fname, "w") as propf: if header_lines: header = '\n'.join(header_lines) propf.write(header) propf.write('\n') propf.write(svn_props_serialized) def svn_read_properties(self, svn_res_path): svn_argv = [self._svn_executable, 'proplist', '--verbose', svn_res_path] self.trace_svn_command(svn_argv) retv = subprocess.check_output(svn_argv, universal_newlines=True) prop_lines = retv.splitlines() prop_file_parser = SvnPropFileParser() return prop_file_parser.parse_property_file_content(prop_lines) def svn_commit_wc(self, comment_lines, wc_dir): tmp_fname = self.save_comment_lines_tmpf(comment_lines) svn_argv = [self._svn_executable, 'ci', '-F', tmp_fname, wc_dir] self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) def svn_import_wc(self, comment_lines, wc_dir, svn_url, global_ignores=None, quiet=False): # svn import -F --auto-props --config-option config:miscellany:global-ignores=.git wc_dir svn_url # e.g. svn_url = https://visvn.fe.hhi.de/svn/svn_CMakeBuildClone/branches/imports/3.10.1-1 tmp_fname = self.save_comment_lines_tmpf(comment_lines) svn_argv = [self._svn_executable, 'import', '-F', tmp_fname, '--auto-props'] # Add any global ignores. if global_ignores: svn_argv.extend(['--config-option', 'config:miscellany:global-ignores=' + ' '.join(global_ignores)]) if quiet: svn_argv.append('-q') # finalize the command line svn_argv.extend([wc_dir, svn_url]) self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) def svn_set_properties_url(self, svn_url, svn_props, work_dir=None): if svn_props.is_empty(): return if self.has_svnmucc(): self._svn_set_properties_url_svnmucc(svn_url, svn_props) else: raise Exception("svn_set_properties_url() requires svnmucc which is not available.") def _svn_set_properties_url_svnmucc(self, svn_url, svn_props): if svn_props.is_empty(): return tmp_files = [] try: svn_argv = [self._svnmucc_executable] (svn_url_prefix, svn_path) = self.svn_split_url(svn_url) for prop in svn_props.get_property_list(): prop_values = svn_props.get_property(prop) if len(prop_values) > 1: tmp_fname = self.svn_save_property_values_tmpf(prop_values) tmp_files.append(tmp_fname) svn_argv.extend(['propsetf', prop, tmp_fname, svn_path]) else: svn_argv.extend(['propset', prop, prop_values[0], svn_path]) svn_argv.append('-m') svn_argv.append("Properties inserted by {0}".format(self._prog_name)) svn_argv.extend(['-U', svn_url_prefix]) self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) finally: for pth in tmp_files: if os.path.exists(pth): os.remove(pth) def svn_set_properties_wc(self, svn_props, work_dir): if svn_props.is_empty(): return tmp_files = [] try: for prop in svn_props.get_property_list(): prop_values = svn_props.get_property(prop) if len(prop_values) > 1: tmp_fname = self.svn_save_property_values_tmpf(prop_values) tmp_files.append(tmp_fname) svn_argv = [self._svn_executable, 'propset', prop, '-F', tmp_fname, work_dir] else: svn_argv = [self._svn_executable, 'propset', prop, prop_values[0], work_dir] self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) finally: for pth in tmp_files: if os.path.exists(pth): os.remove(pth) def svn_remote_copy(self, comment_lines, svn_url_src, svn_url_dst, create_intermediate_folders=True): tmp_fname = self.save_comment_lines_tmpf(comment_lines) svn_argv = [self._svn_executable, 'copy', '-F', tmp_fname] if create_intermediate_folders: svn_argv.append('--parents') svn_argv.extend([svn_url_src, svn_url_dst]) self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) self.remove_tmp_file(tmp_fname) def svn_remote_rm(self, svn_url, comment_lines): tmp_fname = self.save_comment_lines_tmpf(comment_lines) svn_argv = [self._svn_executable, 'rm', '-F', tmp_fname, svn_url] self.trace_svn_command(svn_argv) if self._dry_run: self._logger.warning("dry run: {0}".format(' '.join(svn_argv))) else: util.subproc_check_call_flushed(svn_argv) self.remove_tmp_file(tmp_fname) def svn_split_url(self, svn_url): svn_url_norm = svn_url.rstrip('/') re_match = re.match(r'^(.+)/([^/]+)$', svn_url_norm) if re_match: svn_root_url = re_match.group(1) svn_url_path = "/{}".format(re_match.group(2)) else: raise Exception("SVN URL {0} not supported.".format(svn_url)) return svn_root_url, svn_url_path def trace_svn_command(self, svn_argv): self._cmd_tracer.trace_command(svn_argv) HM-HM-18.0/cmake/CMakeBuild/cmake/000077500000000000000000000000001442026013100163415ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/cmake/modules/000077500000000000000000000000001442026013100200115ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/cmake/modules/BBuildEnv.cmake000066400000000000000000001504651442026013100226400ustar00rootroot00000000000000#[===[.rst: BBuildEnv --------- The module BBuildEnv provides a CMake build environment with functions and macros to access other external SDKs including CodeMeter, CUDASamples, Intel Performance Libraries not yet supported by CMake natively. Other macros ensure consistent build settings for multithreading and provide an abstract CMake generator independent way to configure compiler warnings depending on compiler family and version. This module also provides some system information not yet available by CMake. Unless explicitly disabled by configuration option ``BBuildEnv_EXCLUDE_MODULES`` module ``BBuildEnv`` loads the following submodules to provide additional support for Boost, Qt5, OpenCV, file downloads, MinGW and CPack: ============================== =========================================================== Module Description ============================== =========================================================== :module:`BBuildEnvAddProject` Macros and functions to add standard subproject like console applications, libraries, samples, UTF tests and Qt applications to a standard workspace :module:`BBuildEnvGitSvn` Utility functions to support Git to SVN interoperability. :module:`BBuildEnvDownload` Supports HTTPS downloads of single files at build time :module:`BBuildEnvVersionUtil` Functions to parse version header files :module:`BBuildEnvCPack` Functions helping to create binary distribution packages :module:`BBuildEnvBoost` Macros and functions helping to use locally built Boost libraries. :module:`BBuildEnvOpenCV` Helper functions to copy OpenCV runtime DLLs :module:`BBuildEnvQt5` Helper functions to copy Qt5 runtime DLLs :module:`BBuildEnvMingw` Helper functions to copy MinGW runtime DLLs on Ubuntu ============================== =========================================================== The following modules are not loaded by default as they provide functionality not needed by all main projects. - :module:`BBuildEnvGit` provides macros and functions to checkout Git repositories at configuration time to aggregate them into a single build tree. Similar functionality is provided by module :module:`FetchContent` with slightly different Git clone and update behavior. Configuration Options ^^^^^^^^^^^^^^^^^^^^^ This module evaluates the following variables at load time allowing users to customize its behavior: ``BBuildEnv_EXCLUDE_MODULES`` List of submodules to be excluded from loading. Use ``ALL`` to disable loading any submodule. ``BBuildEnv_DEBUG`` Enable debugging messages. ``BBuildEnv_USE_LIBRARY_NAME_POSTFIX`` A boolean variable to enable a configuration specific library name postfix which allows to install all library or executable variants in the same directory. It's unset/off by default to provide backward compatibility with earlier releases. If enabled executable targets will need a configuration postfix as well. How to Use ^^^^^^^^^^ Include the following statement(s) in your top-level CMakeLists.txt to load this module and its submodules. The modification of :variable:`CMAKE_MODULE_PATH` makes a set of new or patched find modules available as well and is therefore the recommended way to include ``BBuildEnv``. The logic below assumes assumes CMakeBuild is included as an svn:external or as a versioned Git subtree: .. code-block:: cmake # Set module path to subversion or git layout based on the existence of # ${CMAKE_SOURCE_DIR}/CMakeBuild/CMakeBuild/cmake/modules. if( EXISTS "${CMAKE_SOURCE_DIR}/CMakeBuild/CMakeBuild/cmake/modules" ) set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeBuild/CMakeBuild/cmake/modules" ) set( USE_GIT_SUBPROJECTS OFF ) else() file( GLOB CMAKEBUILD_TAGS RELATIVE ${CMAKE_SOURCE_DIR}/CMakeBuild ${CMAKE_SOURCE_DIR}/CMakeBuild/*/CMakeBuild/cmake/modules/BBuildEnv.cmake ) list( LENGTH CMAKEBUILD_TAGS NUM_OF_TAGS ) if( ${NUM_OF_TAGS} EQUAL 1 ) if( CMAKEBUILD_TAGS MATCHES "^([^/]+)/" ) set( CMAKEBUILD_TAG ${CMAKE_MATCH_1} ) endif() if( EXISTS "${CMAKE_SOURCE_DIR}/CMakeBuild/${CMAKEBUILD_TAG}/CMakeBuild/cmake/modules" ) set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeBuild/${CMAKEBUILD_TAG}/CMakeBuild/cmake/modules" ) set( USE_GIT_SUBPROJECTS ON ) else() message( FATAL_ERROR "ERROR: CMakeBuild directory not found: ${CMAKE_SOURCE_DIR}/CMakeBuild/${CMAKEBUILD_TAG}/CMakeBuild/cmake/modules" ) endif() else() message( FATAL_ERROR "ERROR: ${NUM_OF_TAGS} CMakeBuild directories found, exactly one is expected. Directories found: ${CMAKEBUILD_TAGS}" ) endif() endif() # Include a utility module providing functions, macros, and settings to customize the build environment. include( BBuildEnv ) Provided Variables ^^^^^^^^^^^^^^^^^^ Module ``BBuildEnv`` provides the following output variables which are supposed to be treated readonly: ``BBuildEnv_VERSION`` Module's version in decimal dotted format with a maximum of four components. ``BBuildEnv_MSYS`` Set to true when using MSYS. ``BBuildEnv_GENERATOR_ALIAS`` CMake generator specific build directory. It's a plain name without any path separators. ``umake`` Unix Makefiles ``vs16`` Microsoft Visual Studio 2019 ``vs15`` Microsoft Visual Studio 2017 ``vs14`` Microsoft Visual Studio 2015 ``xcode`` Xcode generator, switching between different Xcode versions is currently not supported within a single build tree. ``ninja`` Ninja generator ``BBuildEnv__POSTFIX`` Configuration specific postfix strings to support side-by-side installation in the same directory. ``BBuildEnv_SHARED_DIR_POSTFIX`` A string specific to the shared library configuration to allow for single output directories or installation directories. ``BBuildEnv_OUTPUT_DIR_SUFFIX`` A generator specific relative path to be used in installation rules to support multiple generators or compiler versions in combination with the same installation prefix. ``BBuildEnv_ROOT_DIR`` Optional root directory of CMakeBuild customization files. ``BBuildEnv_SCRIPT_DIR`` Optional path to non-cmake scripts. Provided Functions and Macros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. command:: bb_multithreading The ``bb_multithreading()`` macro adds an imported target ``Threads::Threads`` to enable multithreaded code generation. All multithreaded targets shall have an explicit or implicit dependency on ``Threads::Threads``:: bb_multithreading() .. command:: bb_enable_warnings The ``bb_enable_warnings()`` macro enables CXX compiler warnings in case the selected CMake generator does not by default and accepts parameters to configure warnings as errors and disable warnings given a specific compiler version or compiler family:: bb_enable_warnings([[-]] [warnings-as-errors] [...]) **Parameters:** ``compiler`` The macro supports the following compiler families ``gcc``, ``clang``, ``msvc`` and ``intel``. ``compiler_version`` Compiler version specified as ``major_version`` or ``major_version.minor_version`` to indicate which compiler version the macro should configure. ``warnings-as-errors`` Treat warnings as errors. ``warning_flag`` Compiler specific flag to enable or disable a warning. .. command:: bb_add_subdirectory The ``bb_add_subdirectory()`` macro adds an external in-tree Git subproject provided variable ``USE_GIT_SUBPROJECTS`` is ON. The macro silently assumes the subproject is checked out to ``${CMAKE_SOURCE_DIR}/ext/``. If variable ``USE_GIT_SUBPROJECTS`` is OFF, the macro will invoke :command:`add_subdirectory` for backward compatibility with SVN repositories and subproject aggregation via SVN externals:: bb_add_subdirectory() **Parameters:** ``subproject`` A relative path to an in-tree subproject; e.g. ``BoostAddon/src/lib/LoggerLib`` .. command:: bb_set_target_output_name The ``bb_set_target_output_name`` macro appends a configuration specific postfix to the output name of executable targets if variable ``BBuildEnv_USE_LIBRARY_NAME_POSTFIX`` is ON. If applied to library targets, it will change :prop_tgt:`COMPILE_PDB_NAME_` for static libraries to align the PDB filename with the library filename. CMake's postfix machinery does it for linker generated PDB files but not for compiler generated PDB files:: bb_set_target_output_name( ) **Parameters:** ``target`` An existing target to be modified. .. command:: bb_set_external_dir The ``bb_set_external_dir()`` function searches for a directory given a relative path using a fixed set of root paths. It's intended use is to find a shared folder holding an external project without searching any system paths or cross compiler specific paths:: bb_set_external_dir( []) **Parameters:** ``abs_path`` Absolute path to ``relative_path`` found in one of the default locations. ``dir`` Directory to search for in one of the default locations. An absolute path will be returned as-is. ``OPTIONAL`` Search failure is not treated as an fatal error. **Search Path:** Search path in decreasing order of preference. All paths consisting of undefined environment variables are silently ignored. ``$ENV{PROJ_HOME}`` ``${CMAKE_SOURCE_DIR}/..`` ``${CMAKE_SOURCE_DIR}/../..`` ``$ENV{HOME}/projects`` Ignored on native windows host systems. It is searched when MSYS has been detected or any other non-windows platform. ``$ENV{USERPROFILE}/projects`` Ignored on non-windows host systems. Reserved Identifiers ^^^^^^^^^^^^^^^^^^^^ Avoiding name clashes in CMakeLists.txt or project specific CMake files all projects including module ``BBuildEnv``, or any of its submodules, are advised not to use CMake variables, functions or macros starting with:: BBuildEnv, _BBuildEnv, _bb_, bb_, BB_, _BB_ Users may use variables starting with ``BBuildEnv_`` only to configure the behavior of ``BuildEnv`` modules or submodules or evaluate properties of loaded ``BuildEnv`` modules or submodules exposed through documented variables ``BBuildEnv_``. #]===] if( NOT CMAKE_VERSION VERSION_LESS 3.10 ) include_guard( GLOBAL ) endif() include( "${CMAKE_CURRENT_LIST_DIR}/BBuildEnvVersion.cmake" ) # List of submodules to load by default. set( _BBuildEnvSubmoduleList BBuildEnvAddProject # BBuildEnvDebug BBuildEnvDownload BBuildEnvMingw BBuildEnvVersionUtil BBuildEnvCPack BBuildEnvBoost BBuildEnvQt5 BBuildEnvOpenCV BBuildEnvGitSvn ) foreach( _cmod IN LISTS _BBuildEnvSubmoduleList ) if( DEFINED BBuildEnv_EXCLUDE_MODULES ) if( "${BBuildEnv_EXCLUDE_MODULES}" STREQUAL "ALL" ) break() endif() if( NOT _cmod IN_LIST BBuildEnv_EXCLUDE_MODULES ) include( "${CMAKE_CURRENT_LIST_DIR}/${_cmod}.cmake" OPTIONAL ) endif() else() include( "${CMAKE_CURRENT_LIST_DIR}/${_cmod}.cmake" OPTIONAL ) endif() endforeach() # this macro switches between subversion externals and git dependencies macro( bb_add_subdirectory subdirectory_ ) if( USE_GIT_SUBPROJECTS ) string( REGEX REPLACE "([^/]+).*" "\\1" BASE_DIRECTORY ${subdirectory_} ) add_subdirectory( ${CMAKE_SOURCE_DIR}/ext/${BASE_DIRECTORY}/${subdirectory_} ${CMAKE_BINARY_DIR}/${subdirectory_} ) else() add_subdirectory( ${subdirectory_} ) endif() endmacro() macro( bb_set_target_output_name target_ ) if( BBuildEnv_USE_LIBRARY_NAME_POSTFIX ) get_target_property( _bb_tmp_target_type ${target_} TYPE ) if( _bb_tmp_target_type STREQUAL "EXECUTABLE" ) set_target_properties( ${target_} PROPERTIES OUTPUT_NAME_DEBUG ${target_}${CMAKE_DEBUG_POSTFIX} OUTPUT_NAME_RELWITHDEBINFO ${target_}${CMAKE_RELWITHDEBINFO_POSTFIX} OUTPUT_NAME_MINSIZEREL ${target_}${CMAKE_MINSIZEREL_POSTFIX} ) elseif( MSVC AND (_bb_tmp_target_type STREQUAL "STATIC_LIBRARY" ) ) # message( STATUS "${target_} is static, setting COMPILE_PDB_NAME_DEBUG ..." ) set_target_properties( ${target_} PROPERTIES COMPILE_PDB_NAME_DEBUG ${target_}${CMAKE_DEBUG_POSTFIX} COMPILE_PDB_NAME_RELWITHDEBINFO ${target_}${CMAKE_RELWITHDEBINFO_POSTFIX} ) endif() endif() endmacro() macro( bb_save_find_context fnd_ctx ) if( CMAKE_CROSSCOMPILING ) # find_package must be told not to expect the BOOST libraries inside "CMAKE_FIND_ROOT_PATH". foreach( _v INCLUDE LIBRARY PACKAGE ) if( DEFINED CMAKE_FIND_ROOT_PATH_MODE_${_v} ) # message( STATUS "bb_save_find_context(): CMAKE_FIND_ROOT_PATH_MODE_${_v}=${CMAKE_FIND_ROOT_PATH_MODE_${_v}}" ) set( ${fnd_ctx}_CMAKE_FIND_ROOT_PATH_MODE_${_v} ${CMAKE_FIND_ROOT_PATH_MODE_${_v}} ) set( CMAKE_FIND_ROOT_PATH_MODE_${_v} NEVER ) else() unset( ${fnd_ctx}_CMAKE_FIND_ROOT_PATH_MODE_${_v} ) endif() endforeach() endif() endmacro() macro( bb_restore_find_context fnd_ctx ) if( CMAKE_CROSSCOMPILING ) # Restore CMAKE_FIND_ROOT_PATH settings foreach( _v INCLUDE LIBRARY PACKAGE ) if( DEFINED ${fnd_ctx}_CMAKE_FIND_ROOT_PATH_MODE_${_v} ) set( CMAKE_FIND_ROOT_PATH_MODE_${_v} ${${fnd_ctx}_CMAKE_FIND_ROOT_PATH_MODE_${_v}} ) unset( ${fnd_ctx}_CMAKE_FIND_ROOT_PATH_MODE_${_v} ) # message( STATUS "bb_restore_find_context(): CMAKE_FIND_ROOT_PATH_MODE_${_v}=${CMAKE_FIND_ROOT_PATH_MODE_${_v}}" ) endif() endforeach() endif() endmacro() # # Internal macro to extract the CXX compiler's . version. # macro( _bb_get_cxx_compiler_version_major_minor version_major_minor_ ) string( REGEX REPLACE "([0-9]+)\\.([0-9]+)([0-9.]+)?" "\\1.\\2" ${version_major_minor_} ${CMAKE_CXX_COMPILER_VERSION} ) endmacro() function( bb_get_home_dir home_dir_ ) set( _native FALSE ) if( ARGC EQUAL 2 ) if( ${ARGV1} STREQUAL "NATIVE" ) set( _native TRUE ) else() message( FATAL_ERROR "bb_get_home_dir: argument ${ARGV1} not understood." ) endif() elseif( ARGC GREATER 2 ) message( FATAL_ERROR "bb_get_home_dir: too many arguments specified, expected [NATIVE]." ) endif() if( CMAKE_HOST_WIN32 ) # Force forward slashes on Windows if( BBuildEnv_MSYS ) if( _native ) file( TO_CMAKE_PATH "$ENV{USERPROFILE}" _home_dir ) else() file( TO_CMAKE_PATH "$ENV{HOME}" _home_dir ) endif() else() file( TO_CMAKE_PATH "$ENV{USERPROFILE}" _home_dir ) endif() else() set( _home_dir "$ENV{HOME}" ) endif() set( ${home_dir_} "${_home_dir}" PARENT_SCOPE ) endfunction() macro( bb_set_home_dir home_dir_ ) # backward compatibility bb_get_home_dir( ${home_dir_} ) endmacro() function( bb_get_binary_tool_dir tool_dir_ ) # Location to store scripts and programs generated by CMake to support the build. set( _tool_dir "${CMAKE_BINARY_DIR}/tools" ) if( NOT EXISTS "${_tool_dir}" ) file( MAKE_DIRECTORY "${_tool_dir}" ) endif() set( ${tool_dir_} "${_tool_dir}" PARENT_SCOPE ) endfunction() macro( bb_check_build_type ) # message( STATUS "bb_check_build_type(): entering" ) if( CMAKE_VERSION VERSION_LESS 3.9 ) # Define property GENERATOR_IS_MULTI_CONFIG if it does not exist. get_property( _bb_have_generator_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG DEFINED ) if( NOT _bb_have_generator_is_multi_config ) # message( STATUS "bb_check_build_type(): global property GENERATOR_IS_MULTI_CONFIG is undefined." ) # Property GENERATOR_IS_MULTI_CONFIG is not available define_property( GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG BRIEF_DOCS "True when using a multi-configuration generator." FULL_DOCS "True when using a multi-configuration generator. Builtin property of CMake 3.9.0 or higher." ) if( MSVC OR XCODE ) set_property( GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG 1 ) else() set_property( GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG 0 ) endif() endif() unset( _bb_have_generator_is_multi_config ) endif() get_property( _bb_generator_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG ) # message( STATUS "bb_check_build_type(): GENERATOR_IS_MULTI_CONFIG=${_bb_generator_is_multi_config}" ) if( NOT _bb_generator_is_multi_config ) # set default CMAKE_BUILD_TYPE to Release if not set if( NOT CMAKE_BUILD_TYPE ) set( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE ) endif() endif() unset( _bb_generator_is_multi_config ) # message( STATUS "bb_check_build_type(): leaving" ) endmacro( bb_check_build_type ) macro( bb_multithreading ) if( TARGET Threads::Threads ) message( FATAL_ERROR "bb_multithreading(): target Threads::Threads already exists. Please contact technical support." ) endif() unset( _bb_mt_prop_value ) if( MINGW ) # MinGW may be a native compiler or a cross compiler. find_package( Threads REQUIRED ) #add_compile_options( -mthreads ) #message( STATUS "bb_multithreading(): mingw detected, add_compile_options: -mthreads" ) get_target_property( _bb_mt_prop_value Threads::Threads INTERFACE_COMPILE_OPTIONS ) if( _bb_mt_prop_value ) if( NOT _bb_mt_prop_value STREQUAL "-mthreads" ) message( FATAL_ERROR "bb_multithreading(): target Threads::Threads has unexpected INTERFACE_COMPILE_OPTIONS: ${_bb_mt_prop_value}" ) endif() else() set_target_properties( Threads::Threads PROPERTIES INTERFACE_COMPILE_OPTIONS "-mthreads" ) endif() elseif( CMAKE_CROSSCOMPILING ) find_package( Threads REQUIRED ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Cray" ) find_package( Threads REQUIRED ) else() if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) # Add interface compile/link option -pthread set( THREADS_PREFER_PTHREAD_FLAG ON ) endif() find_package( Threads REQUIRED ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) # A compile option -pthread bound to all enabled languages won't work if CUDA is enabled as a programming language (tested with cmake 3.9.1). # Since NVCC does not understand -pthread, the compile option must be bound to C and CXX. get_target_property( _bb_mt_prop_value Threads::Threads INTERFACE_COMPILE_OPTIONS ) if( _bb_mt_prop_value ) if( _bb_mt_prop_value STREQUAL "-pthread" ) set_target_properties( Threads::Threads PROPERTIES INTERFACE_COMPILE_OPTIONS $<$,$>:-pthread> ) endif() endif() endif() endif() endmacro( bb_multithreading ) macro( bb_enable_warnings ) unset( _bb_warning_options ) # in case the calling context has defined it. _bb_enable_warnings_helper( _bb_warning_options ${ARGN} ) if( DEFINED _bb_warning_options ) message( STATUS "bb_enable_warnings: ${toolset} -> updating warnings flags: ${_bb_warning_options}" ) foreach( _bb_warning_opt IN LISTS _bb_warning_options ) if( MSVC ) # CMake 3.11.0 introduces support for generator expression COMPILE_LANGUAGE. # MSVC generator does not support the generator expression COMPILE_LANGUAGE yet. string( APPEND CMAKE_CXX_FLAGS " ${_bb_warning_opt}" ) string( APPEND CMAKE_C_FLAGS " ${_bb_warning_opt}" ) else() add_compile_options( $<$,$>:${_bb_warning_opt}> ) endif() endforeach() unset( _bb_warning_options ) endif() endmacro() function( _bb_enable_warnings_helper warning_options_ ) #message( STATUS "_bb_enable_warnings_helper(): ${warning_options_} ARGC=${ARGC} ${ARGN}" ) # Translate CMAKE_CXX_COMPILER_ID to a string which compares easily with toolset -> gcc, msvc, clang. if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) set( _bb_warning_compiler_id "gcc" ) elseif( CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang)$" ) if( MSVC ) # No support for clang as MSVC toolset. # message( STATUS "_bb_enable_warnings_helper(): no support for MSVC/clang toolsets yet." ) return() else() set( _bb_warning_compiler_id "clang" ) endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" ) set( _bb_warning_compiler_id "msvc" ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) set( _bb_warning_compiler_id "intel" ) if( APPLE ) # No support for intel yet. return() endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Cray" ) set( _bb_warning_compiler_id "cray" ) return() else() # Not a compiler ID we have support for. return() endif() # Unset a few variables the logic below depends on. The calling context may have defined them. unset( _bb_warning_options ) unset( _bb_tmp_list_var ) if( ${ARGC} GREATER 1 ) set( _bb_tmp_list_var "${ARGN}" ) # Analyze the first argument it may be a toolset, warnings-as-errors or a warning option. list( GET _bb_tmp_list_var 0 _arg1 ) if( "${_arg1}" MATCHES "^(gcc|clang|msvc|intel)" ) #message( STATUS "bb_enable_warnings(): found toolset argument ${ARGV0}" ) if( "${_arg1}" MATCHES "^([a-z]+)-([0-9]+)$" ) # Strip version suffix; e.g. gcc-8 -> gcc set( _bb_warning_toolset "${CMAKE_MATCH_1}" ) # Save major version set( _bb_warning_toolset_version "${CMAKE_MATCH_2}" ) # Get compiler's minor version if( CMAKE_CXX_COMPILER_VERSION MATCHES "^[0-9]+\\.([0-9]+)" ) string( APPEND _bb_warning_toolset_version ".${CMAKE_MATCH_1}" ) endif() elseif( "${_arg1}" MATCHES "^([a-z]+)-([0-9]+\\.[0-9]+)" ) # Strip version suffix; e.g. gcc-4.8 -> gcc set( _bb_warning_toolset "${CMAKE_MATCH_1}" ) set( _bb_warning_toolset_version "${CMAKE_MATCH_2}" ) else() set( _bb_warning_toolset "${_arg1}" ) # Fake a version matching the current compiler version which simplifies the logic below. if( DEFINED bb_compiler_version_major_minor ) set( _bb_warning_toolset_version "${bb_compiler_version_major_minor}" ) else() _bb_get_cxx_compiler_version_major_minor( _bb_warning_toolset_version ) endif() endif() if( ( NOT _bb_warning_toolset STREQUAL _bb_warning_compiler_id ) OR ( NOT _bb_warning_toolset_version VERSION_EQUAL bb_compiler_version_major_minor ) ) # No match for current CXX compiler # message( STATUS "_bb_enable_warnings_helper(): no match for current compiler" ) return() endif() # Drop the toolset from the list of arguments to be processed later on list( REMOVE_AT _bb_tmp_list_var 0 ) endif() endif() if( CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang)$" ) if( NOT XCODE ) set( _bb_warning_options -Wall ) endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) set( _bb_warning_options -Wall -fdiagnostics-show-option ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" ) # Do we have to override the warning level? elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) # Do we have to override the warning level on Windows/MSVC? if( ( NOT MSVC ) AND ( NOT XCODE ) ) set( _bb_warning_options -Wall ) endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Cray" ) # Do we have to override the warning level? endif() #message( STATUS "bb_enable_warnings(): processing additional warning options ${_bb_tmp_list_var}" ) foreach( _bb_v IN LISTS _bb_tmp_list_var ) #message( STATUS "processing ${_bb_v}" ) if( ${_bb_v} STREQUAL "warnings-as-errors" ) if( CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|AppleClang|Clang)$" ) list( APPEND _bb_warning_options "-Werror" ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) if( MSVC ) list( APPEND _bb_warning_options "/WX" ) else() list( APPEND _bb_warning_options "-Werror" ) endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" ) list( APPEND _bb_warning_options "/WX" ) endif() else() list( APPEND _bb_warning_options "${_bb_v}" ) endif() endforeach() if( DEFINED _bb_warning_options ) if( MSVC ) if( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) # Replace -XXX with /XXX avoiding the mix of both option specifications. string( REPLACE "-Q" "/Q" _bb_warning_options "${_bb_warning_options}" ) endif() endif() set( ${warning_options_} ${_bb_warning_options} PARENT_SCOPE ) endif() endfunction( _bb_enable_warnings_helper ) macro( bb_get_program_files_x86 program_files_x86_ ) bb_get_env_icase( ${program_files_x86_} "ProgramFiles(x86)" TO_CMAKE_PATH ) endmacro() macro( bb_get_program_files program_files_ ) bb_get_env_icase( ${program_files_} "ProgramFiles" TO_CMAKE_PATH ) endmacro() macro( bb_get_program_data program_data_ ) bb_get_env_icase( ${program_data_} "ProgramData" TO_CMAKE_PATH ) endmacro() function( bb_get_env_icase env_var_value_ env_var_ ) unset( _path_conversion ) if( ${ARGC} EQUAL 3 ) set( _path_conversion ${ARGV2} ) if( NOT ${_path_conversion} MATCHES "^(TO_CMAKE_PATH|TO_NATIVE_PATH)$" ) message( FATAL_ERROR "illegal conversion ${_path_conversion} specified, use TO_CMAKE_PATH or TO_NATIVE_PATH" ) endif() elseif( ${ARGC} GREATER 3 ) message( FATAL_ERROR "too many arguments specified: ${ARGV}" ) endif() unset( _env_var_value ) if( DEFINED ENV{${env_var_}} ) set( _env_var_value "$ENV{${env_var_}}" ) else() # Mixed-case environment variable? string( TOUPPER "${env_var_}" _env_var_uc ) if( NOT ${_env_var_uc} STREQUAL ${env_var_} ) # Try uppercase environment variable to suit buildbot and possibly other python frameworks. if( DEFINED ENV{${_env_var_uc}} ) set( _env_var_value "$ENV{${_env_var_uc}}" ) endif() endif() endif() if( DEFINED _env_var_value ) if( DEFINED _path_conversion ) file( ${_path_conversion} "${_env_var_value}" _env_var_value ) endif() set( ${env_var_value_} "${_env_var_value}" PARENT_SCOPE ) else() # Should we assign -NOTFOUND instead? if( DEFINED ${env_var_value_} ) unset( ${env_var_value_} PARENT_SCOPE ) endif() endif() endfunction() function( _bb_find_proj_home proj_home_ home_dir_ ) unset( _proj_home ) if( DEFINED ENV{PROJ_HOME} ) # message( STATUS "BBuildEnv: using environment variable PROJ_HOME=$ENV{PROJ_HOME}" ) # Force forward slashes on Windows file( TO_CMAKE_PATH "$ENV{PROJ_HOME}" _proj_home ) if( NOT EXISTS ${_proj_home} ) message( FATAL_ERROR "\ Environment variable PROJ_HOME=${_proj_home} points to a non-existing directory. " ) endif() elseif( EXISTS "${home_dir_}/projects" ) set( _proj_home "${home_dir_}/projects" ) elseif( BBuildEnv_MSYS ) # Check for %USERPROFILE%/projects as a fallback when using MSYS. bb_get_home_dir( _home_dir NATIVE ) if( EXISTS "${_home_dir}/projects" ) set( _proj_home "${_home_dir}/projects" ) endif() endif() if( DEFINED _proj_home ) set( ${proj_home_} "${_proj_home}" PARENT_SCOPE ) endif() endfunction() # # search path: $ENV{PROJ_HOME} ${CMAKE_SOURCE_DIR}/.. ${CMAKE_SOURCE_DIR}/../.. ${bb_home_dir}/projects # function( bb_set_external_dir dir_var_ dir_ ) unset( _dir ) set( _dir_required TRUE ) if( ARGC GREATER 2 ) # Process optional arguments foreach( _arg IN LISTS ARGN ) if( _arg STREQUAL "OPTIONAL" ) set( _dir_required FALSE ) endif() endforeach() endif() if( IS_ABSOLUTE "${dir_}" ) if( NOT EXISTS "${dir_}" ) if( _dir_required ) message( FATAL_ERROR "bb_set_external_dir(): ${dir_} does not exist." ) endif() else() set( _dir "${dir_}" ) endif() else() unset( _search_path ) if( DEFINED ENV{PROJ_HOME} ) file( TO_CMAKE_PATH "$ENV{PROJ_HOME}" _proj_home ) list( APPEND _search_path "${_proj_home}" ) endif() foreach( _dir_tmp "${CMAKE_CURRENT_SOURCE_DIR}/.." "${CMAKE_CURRENT_SOURCE_DIR}/../.." ) if( EXISTS "${_dir_tmp}" ) get_filename_component( _dir_norm "${_dir_tmp}" REALPATH ) list( APPEND _search_path "${_dir_norm}" ) endif() endforeach() bb_get_home_dir( _home_dir ) if( EXISTS "${_home_dir}/projects" ) list( APPEND _search_path "${_home_dir}/projects" ) endif() if( BBuildEnv_MSYS ) bb_get_home_dir( _home_dir NATIVE ) if( EXISTS "${_home_dir}/projects" ) list( APPEND _search_path "${_home_dir}/projects" ) endif() endif() list( REMOVE_DUPLICATES _search_path ) foreach( _path IN LISTS _search_path ) if( EXISTS "${_path}/${dir_}" ) set( _dir "${_path}/${dir_}" ) break() endif() endforeach() if( NOT DEFINED _dir ) if( _dir_required ) message( FATAL_ERROR "bb_set_external_dir(): cannot find ${dir_} in ${_search_path}. You may use the environment variable PROJ_HOME to supplement the default search path." ) endif() else() get_filename_component( _dir "${_dir}" REALPATH ) endif() endif() if( DEFINED _dir ) set( ${dir_var_} "${_dir}" PARENT_SCOPE ) endif() endfunction() # # Additional system information # macro( bb_get_python_script_path script_path_ script_dir_ script_name_ ) if( PYTHONINTERP_FOUND ) if( ${PYTHON_VERSION_STRING} VERSION_LESS 3.0 ) set( ${script_path_} "${script_dir_}/${script_name_}.py" ) else() set( ${script_path_} "${script_dir_}/${script_name_}3.py" ) endif() else() message( FATAL_ERROR "bb_get_python_script_path(): configuration error: python interpreter not found, please contact technical support." ) endif() endmacro() function( _bb_query_linux_pkg_arch pkg_arch_ ) if( bb_dpkg_cmd ) execute_process( COMMAND ${bb_dpkg_cmd} --print-architecture RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _pkg_arch OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( FATAL_ERROR "${bb_dpkg_cmd} --print-architecture failed, please contact technical support." ) endif() set( ${pkg_arch_} "${_pkg_arch}" PARENT_SCOPE ) elseif( bb_rpm_cmd ) execute_process( COMMAND ${bb_rpm_cmd} --eval "%_arch" RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _pkg_arch OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( FATAL_ERROR "${bb_rpm_cmd} --eval %_arch failed, please contact technical support." ) endif() endif() if( DEFINED _pkg_arch ) set( ${pkg_arch_} "${_pkg_arch}" PARENT_SCOPE ) endif() endfunction() function( _bb_find_macosx_isysroot isysroot_ ) if( CMAKE_HOST_APPLE ) execute_process( COMMAND xcrun --sdk macosx --show-sdk-path RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _isysroot OUTPUT_STRIP_TRAILING_WHITESPACE ) # message( STATUS "macosx isysroot discovery: retv_child=${_retv_child} ${_isysroot}" ) if( _retv_child EQUAL 0 ) set( ${isysroot_} ${_isysroot} PARENT_SCOPE ) endif() endif() endfunction() function( _bb_query_system_info system_info_ ) #message( STATUS "_bb_query_system_info: starting system_info=${${system_info_}}" ) if( DEFINED ${system_info_} ) return() endif() #message( STATUS "BBuildEnv: collecting additional system information ..." ) foreach( v _lsb_distro_name _lsb_distro_codename _lsb_distro_version _distro_pkg_fmt _distro_pkg_arch _isysroot ) # message( STATUS "v = ${v}" ) set( ${v} "none" ) endforeach() set( _os_arch "x86_64" ) if( CMAKE_HOST_WIN32 ) # cmake host system: Windows-6.1.7601 set( _system_info "windows" ) if( CMAKE_HOST_SYSTEM MATCHES "[wW][A-Za-z]+-([0-9.]+)" ) set( _lsb_distro_version "${CMAKE_MATCH_1}" ) endif() elseif( CMAKE_HOST_APPLE ) set( _system_info "macosx" ) if( NOT CMAKE_VERSION VERSION_LESS 3.10.0 ) # sw_vers -productVersion cmake_host_system_information( RESULT _lsb_distro_version QUERY OS_RELEASE ) # sw_vers -buildVersion # cmake_host_system_information( RESULT _lsb_distro_version QUERY OS_VERSION ) else() execute_process( COMMAND sw_vers -productVersion OUTPUT_VARIABLE _lsb_distro_version RESULT_VARIABLE _retv_child OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( WARNING "sw_vers -productVersion failed, please contact technical support." ) endif() endif() if( NOT CMAKE_CROSSCOMPILING ) _bb_find_macosx_isysroot( _isysroot ) endif() elseif( CMAKE_HOST_UNIX ) set( _system_info "linux" ) if( CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(i686|x86)$" ) set( _os_arch "x86" ) endif() mark_as_advanced( bb_dpkg_cmd bb_bb_rpm_cmd bb_lsb_release_cmd ) find_program( bb_dpkg_cmd "dpkg" ) if( bb_dpkg_cmd ) set( _distro_pkg_fmt "deb" ) else() find_program( bb_rpm_cmd "rpm" ) if( bb_rpm_cmd ) set( _distro_pkg_fmt "rpm" ) endif() endif() find_program( bb_lsb_release_cmd "lsb_release" ) if( DEFINED ENV{CRAYOS_VERSION} ) set( _lsb_distro_version $ENV{CRAYOS_VERSION} ) set( _lsb_distro_name "cray" ) set( _lsb_distro_codename "none" ) else() if( NOT bb_lsb_release_cmd ) message( WARNING "BBuildEnv: lsb_release not found, no way to retrieve additional linux system information." ) #return() else() execute_process( COMMAND ${bb_lsb_release_cmd} -is RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _lsb_distro_name OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( WARNING "${bb_lsb_release_cmd} -is failed, please contact technical support." ) endif() execute_process( COMMAND ${bb_lsb_release_cmd} -cs RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _lsb_distro_codename OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( WARNING "${bb_lsb_release_cmd} -cs failed, please contact technical support." ) endif() execute_process( COMMAND ${bb_lsb_release_cmd} -rs RESULT_VARIABLE _retv_child OUTPUT_VARIABLE _lsb_distro_version OUTPUT_STRIP_TRAILING_WHITESPACE ) if( NOT _retv_child EQUAL 0 ) message( WARNING "${bb_lsb_release_cmd} -rs failed, please contact technical support." ) endif() endif() endif() _bb_query_linux_pkg_arch( _distro_pkg_arch ) # convert distro name to lowercase string( TOLOWER "${_lsb_distro_name}" _lsb_distro_name ) # convert distro codename to lowercase string( TOLOWER "${_lsb_distro_codename}" _lsb_distro_codename ) # suse does not seem to provide a reasonable codename via lsb_release -cs and issues "n/a". Such # a string is likely to cause problems if used as filename component or evaluated in a similar context. # Hence, it's replace by none. if( _lsb_distro_codename STREQUAL "n/a" ) set( _lsb_distro_codename "none" ) endif() endif() if( _lsb_distro_version STREQUAL "none" ) set( _lsb_distro_version "0.0" ) endif() list( APPEND _system_info ${_os_arch} ${_lsb_distro_name} ${_lsb_distro_codename} ${_lsb_distro_version} ${_distro_pkg_fmt} ${_distro_pkg_arch} ${_isysroot} ) set( ${system_info_} "${_system_info}" CACHE INTERNAL "additional system information" ) endfunction( _bb_query_system_info ) function( _bb_get_platform_dir platform_dir_ ) if( CMAKE_CROSSCOMPILING ) if( CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86)$" ) set( _platform_dir "x86" ) elseif( CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$" ) set( _platform_dir "x86_64" ) else() set( _platform_dir "${CMAKE_SYSTEM_PROCESSOR}" ) endif() else() if( CMAKE_SIZEOF_VOID_P EQUAL 8 ) set( _platform_dir "x86_64" ) else() set( _platform_dir "x86" ) endif() endif() set( ${platform_dir_} "${_platform_dir}" PARENT_SCOPE ) endfunction() function( _bb_get_toolset_subdir toolset_subdir_ compiler_version_ ) unset( _toolset_subdir ) # Assume cmake is able to figure out CMAKE_CXX_COMPILER_ID for all compilers including cross compilers. if( CMAKE_CXX_COMPILER_ID MATCHES "^(AppleClang|Clang)$" ) set( _toolset_subdir "clang-${compiler_version_}" ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) set( _toolset_subdir "gcc-${compiler_version_}" ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" ) set( _toolset_subdir "msvc-${compiler_version_}" ) elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Intel" ) set( _toolset_subdir "intel-${compiler_version_}" ) if( MSVC ) if( NOT DEFINED bb_generator_alias ) message( FATAL_ERROR "MSVC defined but bb_generator_alias is undefined, looks like an internal bug. Please contact technical support." ) else() set( _toolset_subdir "intel-${compiler_version_}-${bb_generator_alias}" ) endif() endif() elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Cray" ) set( _toolset_subdir "cray-${compiler_version_}" ) else() message( FATAL_ERROR "unsupported CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}, please contact technical support." ) endif() if( MINGW ) # MinGW is either a cross compiler or a native compiler. set( _toolset_subdir "gcc-mingw-${compiler_version_}" ) elseif( CMAKE_CROSSCOMPILING ) if( BBuildEnv_DEBUG ) message( STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "cross compiling for ${CMAKE_SYSTEM_PROCESSOR} CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID} cxx_version=${compiler_version_}" ) endif() # message( FATAL_ERROR "no support for this type of cross compiler, please contact technical support." ) endif() if( DEFINED _toolset_subdir ) set( ${toolset_subdir_} "${_toolset_subdir}" PARENT_SCOPE ) endif() endfunction() function( bb_get_os_arch os_arch_ ) list( GET bb_system_info 1 _os_arch ) set( ${os_arch_} "${_os_arch}" PARENT_SCOPE ) endfunction() function( bb_get_target_arch target_arch_ ) list( GET bb_system_info 1 _target_arch ) if( MSVC ) if( CMAKE_SIZEOF_VOID_P EQUAL 4 ) set( _target_arch "x86" ) endif() elseif( MINGW ) if( CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$" ) set( _target_arch "x86_64" ) else() set( _target_arch "x86" ) endif() elseif( CMAKE_CROSSCOMPILING ) # tbd set( _target_arch "${CMAKE_SYSTEM_PROCESSOR}" ) endif() set( ${target_arch_} "${_target_arch}" PARENT_SCOPE ) endfunction() function( bb_get_linux_distro_name distro_name_ ) list( GET bb_system_info 2 _distro_name ) set( ${distro_name_} "${_distro_name}" PARENT_SCOPE ) endfunction() function( bb_get_os_codename os_codename_ ) list( GET bb_system_info 3 _os_codename ) set( ${os_codename_} "${_os_codename}" PARENT_SCOPE ) endfunction() function( bb_get_os_version os_version_ ) list( GET bb_system_info 4 _os_version ) set( ${os_version_} "${_os_version}" PARENT_SCOPE ) endfunction() function( bb_get_linux_pkg_fmt pkg_fmt_ ) list( GET bb_system_info 5 _pkg_fmt ) set( ${pkg_fmt_} "${_pkg_fmt}" PARENT_SCOPE ) endfunction() function( bb_get_linux_pkg_arch pkg_arch_ ) list( GET bb_system_info 6 _pkg_arch ) set( ${pkg_arch_} "${_pkg_arch}" PARENT_SCOPE ) endfunction() function( bb_get_isysroot isysroot_ ) list( GET bb_system_info 7 _isysroot ) set( ${isysroot_} "${_isysroot}" PARENT_SCOPE ) endfunction() function( bb_get_imp_targets_from_components target_list_ target_prefix_ config_ comp1_ ) set( _comp_list ${comp1_} ${ARGN} ) unset( _target_list ) #message( STATUS "bb_get_imp_targets_from_components(): ${_comp_list}" ) string( TOUPPER "${config_}" _config_uc ) set( _target_prop_list INTERFACE_LINK_LIBRARIES_${_config_uc} INTERFACE_LINK_LIBRARIES IMPORTED_LINK_INTERFACE_LIBRARIES_${_config_uc} IMPORTED_LINK_INTERFACE_LIBRARIES ) foreach( _comp IN LISTS _comp_list ) set( _target_name ${target_prefix_}${_comp} ) list( APPEND _target_list ${_target_name} ) foreach( _target_prop IN LISTS _target_prop_list ) get_target_property( _prop_value ${_target_name} ${_target_prop} ) #message( STATUS "${_target_name} ${_target_prop} -> _prop_value=${_prop_value}" ) if( _prop_value ) #message( STATUS "_bb_get_qt5_dlls: Qt5::${_comp}: INTERFACE_LINK_LIBRARIES=${_prop_value}" ) foreach( _lnk_lib ${_prop_value} ) if( _lnk_lib MATCHES "^${target_prefix_}[a-zA-Z]" ) list( APPEND _target_list ${_lnk_lib} ) endif() endforeach() break() endif() endforeach() endforeach() if( DEFINED _target_list ) list( REMOVE_DUPLICATES _target_list ) set( ${target_list_} ${_target_list} PARENT_SCOPE ) endif() endfunction() # Optional argument: NO_PDB_FILES function( bb_get_dsos_from_imp_targets dso_list_ config_ target1_ ) string( TOUPPER "${config_}" _config_uc ) set( _target_list ${target1_} ${ARGN} ) if( NO_PDB_FILES IN_LIST _target_list ) set( _no_pdb_files TRUE ) list( REMOVE_ITEM _target_list NO_PDB_FILES ) else() set( _no_pdb_files FALSE ) endif() unset( _bin_dir ) unset( _dso_list ) # Walk _target_list and collect paths to dlls. foreach( _target ${_target_list} ) # "IMPORTED_LOCATION" "IMPORTED_LOCATION_RELEASE" "IMPORTED_LOCATION_DEBUG" get_target_property( _prop_value ${_target} IMPORTED_LOCATION_${_config_uc} ) if( NOT _prop_value ) message( WARNING "bb_get_dsos_from_imp_targets(): no IMPORTED_LOCATION_${_config_uc} for target ${_target}" ) get_target_property( _prop_value ${_target} IMPORTED_LOCATION ) endif() if( _prop_value ) # Ignore any static libraries get_filename_component( _lib_ext ${_prop_value} EXT ) if( WIN32 ) if( NOT _lib_ext MATCHES "^\\.(dll|DLL)$" ) continue() endif() elseif( APPLE ) if( _lib_ext STREQUAL ".a" ) continue() endif() else() # Linux: extension may have a trailing version number. if( NOT _lib_ext MATCHES "^\\.so" ) continue() endif() endif() # message( STATUS "${_target}: IMPORTED_LOCATION_RELEASE=${_prop_value}" ) if( NOT DEFINED _bin_dir ) get_filename_component( _bin_dir ${_prop_value} DIRECTORY ) endif() list( APPEND _dso_list ${_prop_value} ) if( _config_uc STREQUAL "DEBUG" ) if( WIN32 AND NOT ${_no_pdb_files} ) # Add PDB file if available get_filename_component( _filenm ${_prop_value} NAME_WE ) if( EXISTS "${_bin_dir}/${_filenm}.pdb" ) list( APPEND _dso_list "${_bin_dir}/${_filenm}.pdb" ) endif() endif() endif() endif() endforeach() if( DEFINED _dso_list ) set( ${dso_list_} ${_dso_list} PARENT_SCOPE ) endif() endfunction() function( bb_file action_ input_path_ output_path_ ) if( "${action_}" STREQUAL "TO_SHORT_PATH" ) if( NOT CMAKE_HOST_WIN32 ) message( FATAL_ERROR "Short path conversion is only supported on Windows host systems." ) endif() endif() if( "${action_}" MATCHES "^(TO_NATIVE_PATH|TO_SHORT_PATH)$" ) if( CMAKE_HOST_WIN32 ) if( CMAKE_GENERATOR STREQUAL "MinGW Makefiles" ) # Painful hack to get backslashes as the CMake generator mgwmake seems to enable Linux path conversion # rather than Windows path conversion. # example: C:/Program Files -> C:/Program\ Files string( REPLACE "/" "\\" _native_path "${input_path_}" ) else() file( TO_NATIVE_PATH "${input_path_}" _native_path ) endif() else() file( TO_NATIVE_PATH "${input_path_}" _native_path ) endif() # message( STATUS "input_path='${input_path_}' native_path='${_native_path}'" ) if( "${action_}" STREQUAL "TO_NATIVE_PATH" ) set( ${output_path_} "${_native_path}" PARENT_SCOPE ) endif() endif() if( "${action_}" STREQUAL "TO_SHORT_PATH" ) find_program( BB_SHELL_PROG "cmd.exe" ) bb_file( TO_NATIVE_PATH "${BB_SHELL_PROG}" script_launcher ) set( script_cmd_line "/c" ) bb_get_binary_tool_dir( _tool_dir ) if( NOT EXISTS "${_tool_dir}/get_short_path.cmd" ) file( WRITE "${_tool_dir}/get_short_path.cmd" "@echo off\n" "echo %~s1\n" ) endif() bb_file( TO_NATIVE_PATH "${_tool_dir}/get_short_path.cmd" cmd_script ) string( APPEND script_cmd_line " ${cmd_script}" ) string( APPEND script_cmd_line " \"${_native_path}\"" ) # separate_arguments( script_args NATIVE_COMMAND "${script_cmd_line}" ) # message( STATUS "Launching: ${script_launcher} ${script_args}" ) execute_process( COMMAND "${script_launcher}" ${script_args} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE retv OUTPUT_VARIABLE short_path OUTPUT_STRIP_TRAILING_WHITESPACE ) if( retv EQUAL 0 ) #message( STATUS "python interpreter (short path): ${short_path}" ) set( ${output_path_} "${short_path}" PARENT_SCOPE ) else() message( FATAL_ERROR "short path conversion failed: ${retv}, please contact technical support." ) endif() endif() endfunction() # # Internal macro to setup the build environment. # macro( bb_build_env_setup ) message( STATUS "Setting up BBuildEnv ${BBuildEnv_VERSION}" ) unset( BBuildEnv_ROOT_DIR ) unset( BBuildEnv_SCRIPT_DIR ) set( BBuildEnv_MSYS FALSE ) if( CMAKE_HOST_WIN32 ) if( DEFINED ENV{MSYSTEM} ) message( STATUS "BBuildEnv: MSYS[2] platform detected." ) set( BBuildEnv_MSYS TRUE ) endif() endif() bb_check_build_type() if( EXISTS "${CMAKE_CURRENT_LIST_DIR}/../.." ) get_filename_component( BBuildEnv_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH ) if( EXISTS "${BBuildEnv_ROOT_DIR}/bin" ) set( BBuildEnv_SCRIPT_DIR "${BBuildEnv_ROOT_DIR}/bin" ) endif() endif() _bb_query_system_info( bb_system_info ) # message( STATUS "bb_system_info: ${bb_system_info}" ) bb_get_home_dir( bb_home_dir ) _bb_find_proj_home( bb_proj_home "${bb_home_dir}" ) # Add a cmake generator alias unset( bb_generator_alias ) if( CMAKE_GENERATOR STREQUAL "Unix Makefiles" ) set( bb_generator_alias "umake" ) elseif( CMAKE_GENERATOR STREQUAL "Xcode" ) set( bb_generator_alias "xcode" ) elseif( CMAKE_GENERATOR MATCHES "Visual Studio ([0-9][0-9])" ) set( bb_generator_alias "vs${CMAKE_MATCH_1}" ) elseif( CMAKE_GENERATOR STREQUAL "Ninja" ) set( bb_generator_alias "ninja" ) elseif( CMAKE_GENERATOR STREQUAL "MinGW Makefiles" ) set( bb_generator_alias "mgwmake" ) else() message( WARNING "BBuildEnv.cmake: generator '${CMAKE_GENERATOR}' is not fully supported yet, please contact technical support for further information." ) #return() string( TOLOWER "${CMAKE_GENERATOR}" _generator_uc ) string( REPLACE " " "_" bb_generator_alias "${_generator_uc}" ) unset( _generator_uc ) endif() #message( STATUS "bb_generator_alias: ${bb_generator_alias}" ) _bb_get_cxx_compiler_version_major_minor( bb_compiler_version_major_minor ) _bb_get_toolset_subdir( bb_toolset_subdir ${bb_compiler_version_major_minor} ) _bb_get_platform_dir( bb_platform_dir ) # set standard output directories: gcc-5.4/x86_64 if( DEFINED bb_generator_alias ) set( BBuildEnv_GENERATOR_ALIAS "${bb_generator_alias}" ) set( bb_default_output_dir "${bb_generator_alias}/${bb_toolset_subdir}/${bb_platform_dir}" ) else() set( bb_default_output_dir "${bb_toolset_subdir}/${bb_platform_dir}" ) endif() # BBuildEnv_OUTPUT_DIR_SUFFIX could be a cache variable to make it customizable. set( BBuildEnv_OUTPUT_DIR_SUFFIX "${bb_default_output_dir}" ) # the deploy folder may be used to save installer packages. set( bb_deploy_dir "${CMAKE_SOURCE_DIR}/deploy" ) if( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT ) set( CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install" CACHE PATH "Standard install prefix" FORCE ) endif() if( BUILD_SHARED_LIBS ) set( BBuildEnv_SHARED_DIR_POSTFIX "-shared" ) else() unset( BBuildEnv_SHARED_DIR_POSTFIX ) endif() if( NOT DEFINED BBuildEnv_USE_LIBRARY_NAME_POSTFIX ) set( BBuildEnv_USE_LIBRARY_NAME_POSTFIX OFF CACHE BOOL "Enable library name postfix" ) endif() #set( BBuildEnv_RELEASE_POSTFIX "" ) set( BBuildEnv_DEBUG_POSTFIX "-d" ) set( BBuildEnv_RELWITHDEBINFO_POSTFIX "-rd" ) set( BBuildEnv_MINSIZEREL_POSTFIX "-mr" ) if( BBuildEnv_USE_LIBRARY_NAME_POSTFIX ) set( CMAKE_DEBUG_POSTFIX ${BBuildEnv_DEBUG_POSTFIX} ) set( CMAKE_RELWITHDEBINFO_POSTFIX ${BBuildEnv_RELWITHDEBINFO_POSTFIX} ) set( CMAKE_MINSIZEREL_POSTFIX ${BBuildEnv_MINSIZEREL_POSTFIX} ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib${BBuildEnv_SHARED_DIR_POSTFIX}/${BBuildEnv_OUTPUT_DIR_SUFFIX}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin${BBuildEnv_SHARED_DIR_POSTFIX}/${BBuildEnv_OUTPUT_DIR_SUFFIX}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" ) else() # Using CMake's default library name convention which is the same for all configurations. set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/lib/${BBuildEnv_OUTPUT_DIR_SUFFIX}/debug${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}/lib/${BBuildEnv_OUTPUT_DIR_SUFFIX}/release${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_SOURCE_DIR}/lib/${BBuildEnv_OUTPUT_DIR_SUFFIX}/relwithdebinfo${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_SOURCE_DIR}/lib/${BBuildEnv_OUTPUT_DIR_SUFFIX}/minsizerel${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/bin/${BBuildEnv_OUTPUT_DIR_SUFFIX}/debug${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}/bin/${BBuildEnv_OUTPUT_DIR_SUFFIX}/release${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_SOURCE_DIR}/bin/${BBuildEnv_OUTPUT_DIR_SUFFIX}/relwithdebinfo${BBuildEnv_SHARED_DIR_POSTFIX}" ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_SOURCE_DIR}/bin/${BBuildEnv_OUTPUT_DIR_SUFFIX}/minsizerel${BBuildEnv_SHARED_DIR_POSTFIX}" ) endif() endmacro( bb_build_env_setup ) #message( STATUS "BBuildEnv.cmake: starting: ${CMAKE_GENERATOR}" ) # Setup the build environment bb_build_env_setup() #message( STATUS "BBuildEnv.cmake: leaving" ) HM-HM-18.0/cmake/CMakeBuild/cmake/modules/BBuildEnvDebug.cmake000066400000000000000000000142721442026013100236020ustar00rootroot00000000000000#[===[.rst: BBuildEnvDebug -------------- Internal module providing macros and functions for debugging. It won't be included by BBuildEnv by default. #]===] if( NOT CMAKE_VERSION VERSION_LESS 3.10 ) include_guard( GLOBAL ) endif() function( bb_dump_cmake_system_info ) message( STATUS "bb_dump_cmake_system_info() entering" ) message( STATUS "CMAKE_COMMAND: ${CMAKE_COMMAND}" ) message( STATUS "CMAKE_VERSION: ${CMAKE_VERSION}" ) message( STATUS "CMAKE_ROOT: ${CMAKE_ROOT}" ) message( STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}" ) message( STATUS "CMAKE_SIZEOF_VOID_P: ${CMAKE_SIZEOF_VOID_P}" ) if( MINGW ) message( STATUS "MINGW: on" ) endif() if( CMAKE_CROSSCOMPILING ) message( STATUS "CMAKE_CROSSCOMPILING: on" ) endif() # target operating system: Linux, Windows, Darwin, Android message( STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}" ) message( STATUS "CMAKE_HOST_SYSTEM: ${CMAKE_HOST_SYSTEM}" ) message( STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}" ) # examples: x86_64 (ubuntu 16.04, macosx 10.12) # AMD64 (windows 7 64-bit, -A x64, -A Win32) message( STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}" ) message( STATUS "CMAKE_HOST_SYSTEM_PROCESSOR: ${CMAKE_HOST_SYSTEM_PROCESSOR}" ) if( CMAKE_HOST_APPLE ) message( STATUS "CMAKE_HOST_APPLE: on" ) endif() if( CMAKE_HOST_UNIX ) message( STATUS "CMAKE_HOST_UNIX: on" ) endif() if( CMAKE_HOST_WIN32 ) message( STATUS "CMAKE_HOST_WIN32: on" ) endif() if( NOT CMAKE_VERSION VERSION_LESS 3.10.0 ) cmake_host_system_information( RESULT os_name QUERY OS_NAME ) cmake_host_system_information( RESULT os_release QUERY OS_RELEASE ) cmake_host_system_information( RESULT os_version QUERY OS_VERSION ) cmake_host_system_information( RESULT os_platform QUERY OS_PLATFORM ) message( STATUS "OS_NAME: ${os_name}" ) message( STATUS "OS_RELEASE: ${os_release}" ) message( STATUS "OS_VERSION: ${os_version}" ) message( STATUS "OS_PLATFORM: ${os_platform}" ) endif() message( STATUS "CMAKE_PROGRAM_PATH: ${CMAKE_PROGRAM_PATH}" ) message( STATUS "CMAKE_SYSTEM_PROGRAM_PATH: ${CMAKE_SYSTEM_PROGRAM_PATH}" ) message( STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}" ) message( STATUS "CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}" ) if( CMAKE_CXX_COMPILER_LOADED ) message( STATUS "CMAKE_CXX_COMPILER_LOADED: on" ) endif() # expected: GNU, Clang, AppleClang, MSVC, message( STATUS "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}" ) message( STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}" ) message( STATUS "CMAKE_CXX_COMPILER_VERSION: ${CMAKE_CXX_COMPILER_VERSION}" ) #message( STATUS "cxx compile features: ${CMAKE_CXX_COMPILE_FEATURES}" ) if( CMAKE_CXX_COMPILER_ARCHITECTURE_ID ) # CMAKE_CXX_COMPILER_ARCHITECTURE_ID is defined but empty on Linux message( STATUS "CMAKE_CXX_COMPILER_ARCHITECTURE_ID: ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" ) endif() if( MSVC ) message( STATUS "CMAKE_VS_PLATFORM_NAME: ${CMAKE_VS_PLATFORM_NAME}" ) message( STATUS "CMAKE_VS_PLATFORM_NAME: ${CMAKE_VS_PLATFORM_NAME}" ) message( STATUS "CMAKE_VS_PLATFORM_TOOLSET: ${CMAKE_VS_PLATFORM_TOOLSET}" ) message( STATUS "MSVC_VERSION: ${MSVC_VERSION}" ) if( NOT CMAKE_VERSION VERSION_LESS 3.12.0 ) message( STATUS "MSVC_TOOLSET_VERSION: ${MSVC_TOOLSET_VERSION}" ) endif() if( CMAKE_CSharp_COMPILER_WORKS ) message( STATUS "CMAKE_CSharp_COMPILER_ID: ${CMAKE_CSharp_COMPILER_ID}" ) message( STATUS "CMAKE_CSharp_COMPILER: ${CMAKE_CSharp_COMPILER}" ) message( STATUS "CMAKE_CSharp_COMPILER_VERSION: ${CMAKE_CSharp_COMPILER_VERSION}" ) endif() endif() if( XCODE ) if( CMAKE_Swift_COMPILER_ID ) message( STATUS "CMAKE_Swift_COMPILER_ID: ${CMAKE_Swift_COMPILER_ID}" ) message( STATUS "CMAKE_Swift_COMPILER: ${CMAKE_Swift_COMPILER}" ) message( STATUS "CMAKE_Swift_COMPILER_VERSION: ${CMAKE_Swift_COMPILER_VERSION}" ) endif() endif() get_property( _bb_generator_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG ) if( _bb_generator_is_multi_config ) message( STATUS "CMAKE_CONFIGURATION_TYPES: ${CMAKE_CONFIGURATION_TYPES}" ) else() message( STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" ) endif() unset( _bb_generator_is_multi_config ) message( STATUS "bb_system_info: ${bb_system_info}" ) bb_get_target_arch( _bb_value ) message( STATUS "bb_get_target_arch: ${_bb_value}" ) bb_get_home_dir( _bb_value ) message( STATUS "bb_get_home_dir: ${_bb_value}" ) if( CMAKE_HOST_WIN32 ) bb_get_program_files_x86( _bb_value ) message( STATUS "bb_get_program_files_x86: ${_bb_value}" ) bb_get_program_files( _bb_value ) message( STATUS "bb_get_program_files: ${_bb_value}" ) bb_get_program_data( _bb_value ) message( STATUS "bb_get_program_data: ${_bb_value}" ) endif() message( STATUS "bb_dump_cmake_system_info() leaving" ) endfunction( bb_dump_cmake_system_info ) function( bb_dump_target_properties target_ prop1_ ) if( NOT TARGET ${target_} ) message( WARNING "target ${target_} does not exist." ) return() endif() set( _prop_list ${prop1_} ) list( APPEND _prop_list ${ARGN} ) list( LENGTH _prop_list _prop_list_len ) message( STATUS "bb_dump_target_properties: len=${_prop_list_len} ${_prop_list}" ) foreach( _prop ${_prop_list} ) get_target_property( _prop_value ${target_} ${_prop} ) if( _prop_value ) message( STATUS "${target_}: ${_prop}=${_prop_value}" ) endif() endforeach() message( STATUS "bb_dump_target_properties: leaving" ) endfunction() macro( bb_dump_imported_target_properties target_ ) bb_dump_target_properties( ${target_} IMPORTED_LOCATION IMPORTED_IMPLIB INTERFACE_INCLUDE_DIRECTORIES INTERFACE_COMPILE_DEFINITIONS INTERFACE_LINK_LIBRARIES ) endmacro() HM-HM-18.0/cmake/CMakeBuild/cmake/modules/BBuildEnvLldb.cmake000066400000000000000000000142151442026013100234260ustar00rootroot00000000000000#.rst: # BBuildEnvLldb # ------------- # # Functions to update an LLDB init file. # # :: # # bb_lldbinit_update(ADD [OUTPUT ]) # # Add or replace the content of section labeled with ``marker`` in file ``lldbinit_file``. # # :: # # bb_lldbinit_update(REMOVE [OUTPUT ]) # # Remove the section labeled with ``marker`` from file ``lldbinit_file``. # if( NOT CMAKE_VERSION VERSION_LESS 3.10 ) include_guard( GLOBAL ) endif() function( bb_lldbinit_update action_ lldbinit_file_ marker_ ) set( _fnc_name "bb_lldbinit_update" ) #message( STATUS "${_fnc_name}: entering" ) if( NOT ${action_} MATCHES "^(ADD|REMOVE)$" ) message( FATAL_ERROR "Unknown update action ${action_} specified, expected ADD or REMOVE." ) endif() if( IS_ABSOLUTE "${lldbinit_file_}" ) set( _lldbinit_file "${lldbinit_file_}" ) else() set( _lldbinit_file "${CMAKE_CURRENT_SOURCE_DIR}/${lldbinit_file_}" ) endif() set( _lldbinit_out_file "${_lldbinit_file}" ) unset( _lldbinit_lines ) # Parse command line and handle optional arguments if( ARGC GREATER 3 ) #message( STATUS "${_fnc_name}: optional arguments ${ARGN}" ) set( _opt_args ${ARGN} ) list( LENGTH _opt_args _opt_args_cnt ) while( _opt_args_cnt GREATER 0 ) list( GET _opt_args 0 _arg ) list( REMOVE_AT _opt_args 0 ) #message( STATUS "${_fnc_name}: processing optional argument ${_arg}" ) if( _arg STREQUAL "OUTPUT" ) # Pick the next argument and stop processing list( LENGTH _opt_args _opt_args_cnt ) if( _opt_args_cnt EQUAL 1 ) list( GET _opt_args 0 _lldbinit_out_file ) if( NOT IS_ABSOLUTE "${_lldbinit_out_file}" ) set( _lldbinit_out_file "${CMAKE_CURRENT_SOURCE_DIR}/${_lldbinit_out_file}" ) endif() else() message( FATAL_ERROR "${_fnc_name}: illegal number of arguments." ) endif() break() else() list( APPEND _lldbinit_lines ${_arg} ) endif() list( LENGTH _opt_args _opt_args_cnt ) endwhile() endif() #message( STATUS "${_fnc_name}: new_content: ${_lldbinit_lines}" ) #message( STATUS "${_fnc_name}: input_file: ${_lldbinit_file}" ) #message( STATUS "${_fnc_name}: output_file: ${_lldbinit_out_file}" ) set( _regex_start "^#[ \t]*<${marker_}>" ) set( _regex_end "^#[ \t]*" ) unset( _lldbinit_section_orig ) unset( _lldbinit_section_new ) unset( _lldbinit_orig_top ) unset( _lldbinit_orig_bottom ) set( _start_section_cnt 0 ) set( _end_section_cnt 0 ) if( action_ STREQUAL "ADD" ) set( _update_lldbinit_file TRUE ) elseif( action_ STREQUAL "REMOVE" ) set( _update_lldbinit_file FALSE ) endif() # Create the new lldbinit section foreach( _line IN LISTS _lldbinit_lines ) string( APPEND _lldbinit_section_new "${_line}" "\n" ) endforeach() # Create section start and section end lines _bb_lldbinit_create_marker_lines( ${marker_} _lldbinit_section_start _lldbinit_section_end ) if( EXISTS "${_lldbinit_file}" ) file( STRINGS ${_lldbinit_file} _lldbinit_lines_orig ) #message( STATUS "bb_update_lldbinit(): |${_lldbinit_lines_orig}|" ) #message( STATUS "----" ) #message( STATUS ${_lldbinit_lines_orig} ) #message( STATUS "----" ) foreach( _line IN LISTS _lldbinit_lines_orig ) #message( STATUS "bb_update_lldbinit(): processing ${_line}" ) if( _line MATCHES "${_regex_start}" ) math( EXPR _start_section_cnt "${_start_section_cnt} + 1" ) continue() endif() if( _line MATCHES "${_regex_end}" ) math( EXPR _end_section_cnt "${_end_section_cnt} + 1" ) continue() endif() if( ( _start_section_cnt EQUAL 1 ) AND ( _end_section_cnt EQUAL 0 ) ) # Extract existing section string( APPEND _lldbinit_section_orig "${_line}" "\n" ) elseif( ( _start_section_cnt EQUAL 0 ) AND ( _end_section_cnt EQUAL 0 ) ) string( APPEND _lldbinit_orig_top "${_line}" "\n" ) elseif( ( _start_section_cnt EQUAL 1 ) AND ( _end_section_cnt EQUAL 1 ) ) string( APPEND _lldbinit_orig_bottom "${_line}" "\n" ) endif() endforeach() # Check section counters if( ( _start_section_cnt EQUAL 1 ) AND ( _end_section_cnt EQUAL 1 ) ) #message( STATUS "_lldbinit_orig_top: ${_lldbinit_orig_top}" ) #message( STATUS "_lldbinit_section_orig: ${_lldbinit_section_orig}" ) #message( STATUS "_lldbinit_orig_bottom: ${_lldbinit_orig_bottom}" ) if( action_ STREQUAL "ADD" ) if( "${_lldbinit_section_orig}" STREQUAL "${_lldbinit_section_new}" ) set( _update_lldbinit_file FALSE ) endif() elseif( action_ STREQUAL "REMOVE" ) set( _update_lldbinit_file TRUE ) endif() elseif( ( _start_section_cnt EQUAL 0 ) AND ( _end_section_cnt EQUAL 0 ) ) else() # Unsupported format message( WARNING "${_fnc_name}: unsupported lldbinit, check number of tags." ) return() endif() endif() if( NOT EXISTS ${_lldbinit_out_file} ) set( _update_lldbinit_file TRUE ) endif() if( _update_lldbinit_file ) message( STATUS "${_fnc_name}: updating ${_lldbinit_out_file}, section=${marker_}" ) if( action_ STREQUAL "ADD" ) file( WRITE ${_lldbinit_out_file} "${_lldbinit_orig_top}" "${_lldbinit_section_start}" "${_lldbinit_section_new}" "${_lldbinit_section_end}" "${_lldbinit_orig_bottom}" ) elseif( action_ STREQUAL "REMOVE" ) file( WRITE ${_lldbinit_out_file} "${_lldbinit_orig_top}" "${_lldbinit_orig_bottom}" ) endif() endif() #message( STATUS "${_fnc_name}: leaving" ) endfunction( bb_lldbinit_update ) function( _bb_lldbinit_create_marker_lines marker_ start_marker_ end_marker_ ) string( TIMESTAMP _time_now "%Y-%m-%d %H:%M:%S" ) set( ${start_marker_} "#<${marker_}> - automatically inserted at ${_time_now}, don't remove.\n" PARENT_SCOPE ) #set( ${start_marker_} "#<${marker_}> - automatically inserted, don't remove.\n" PARENT_SCOPE ) set( ${end_marker_} "# - automatically inserted, don't remove.\n" PARENT_SCOPE ) endfunction( _bb_lldbinit_create_marker_lines ) HM-HM-18.0/cmake/CMakeBuild/cmake/modules/BBuildEnvMingw.cmake000066400000000000000000000054541442026013100236370ustar00rootroot00000000000000#[[.rst: BBuildEnvMingw -------------- Functions and macros supporting MinGW development. .. command:: bb_add_target_CopyMingwRuntimeFiles The ``bb_add_target_CopyMingwRuntimeFiles()`` macro adds a custom target ``CopyMingwRuntimeFiles`` to copy MinGW dlls to :variable:`CMAKE_RUNTIME_OUTPUT_DIRECTORY_`. #]] if( NOT CMAKE_VERSION VERSION_LESS 3.10 ) include_guard( GLOBAL ) endif() macro( bb_add_target_CopyMingwRuntimeFiles ) if( MINGW AND CMAKE_CROSSCOMPILING ) if( NOT TARGET CopyMingwRuntimeFiles ) if( NOT DEFINED bb_MINGW_RUNTIME_FILES ) message( FATAL_ERROR "\ No MinGW runtime files defined, check your toolchain file and define bb_MINGW_RUNTIME_FILES or don't call bb_add_target_CopyMingwRuntimeFiles()." ) endif() if( NOT CMAKE_VERSION VERSION_LESS 3.8 ) add_custom_target( CopyMingwRuntimeFiles ALL ${CMAKE_COMMAND} -E make_directory $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}> COMMAND ${CMAKE_COMMAND} -E copy_if_different ${bb_MINGW_RUNTIME_FILES} $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}> VERBATIM COMMAND_EXPAND_LISTS ) else() add_custom_target( CopyMingwRuntimeFiles ALL ${CMAKE_COMMAND} -E make_directory $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}> COMMAND ${CMAKE_COMMAND} -E copy_if_different ${bb_MINGW_RUNTIME_FILES} $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}> ) endif() endif() endif() endmacro() HM-HM-18.0/cmake/CMakeBuild/cmake/modules/BBuildEnvVersion.cmake000066400000000000000000000011251442026013100241720ustar00rootroot00000000000000# # WARNING: This file is automatically generated by CMake and any manual changes will # be overridden by the next build. # If you need to change anything here, please update the configure template BBuildEnvVersion.cmake.in. # set( BBuildEnv_VERSION_MAJOR 3 ) set( BBuildEnv_VERSION_MINOR 14 ) set( BBuildEnv_VERSION_PATCH 4 ) set( BBuildEnv_VERSION_TWEAK 4 ) # BBuildEnv version in decimal dotted format as supported by CMake's version compare operations. set( BBuildEnv_VERSION "${BBuildEnv_VERSION_MAJOR}.${BBuildEnv_VERSION_MINOR}.${BBuildEnv_VERSION_PATCH}.${BBuildEnv_VERSION_TWEAK}" ) HM-HM-18.0/cmake/CMakeBuild/cmake/toolchains/000077500000000000000000000000001442026013100205045ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/cmake/toolchains/aarch64-linux-gnu-gcc-ubuntu1804.cmake000066400000000000000000000037661442026013100272650ustar00rootroot00000000000000# name of the target operating system set( CMAKE_SYSTEM_NAME Linux ) set( CMAKE_SYSTEM_PROCESSOR aarch64 ) set( GNU_MACHINE "aarch64-linux-gnu" ) # which compilers to use for C and C++ set( CMAKE_C_COMPILER ${GNU_MACHINE}-gcc ) set( CMAKE_CXX_COMPILER ${GNU_MACHINE}-g++ ) # here is the target environment located if( NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE ) set( ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX} ) endif() list( APPEND CMAKE_FIND_ROOT_PATH ${ARM_LINUX_SYSROOT} ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) # Ubuntu/amd64 + foreign architecture arm64 set( CMAKE_LIBRARY_PATH /usr/lib/${GNU_MACHINE}-linux-gnu ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH ) #set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) set( USE_OPENCV_TOOLCHAIN_FLAGS ON ) if( USE_OPENCV_TOOLCHAIN_FLAGS ) # --- # Snatched from OpenCV 3.4.2-1 # --- #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi") set( CMAKE_CXX_FLAGS_INIT "-fdata-sections -Wa,--noexecstack -fsigned-char" ) set( CMAKE_C_FLAGS_INIT "-fdata-sections -Wa,--noexecstack -fsigned-char" ) set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") #set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}") #set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}") #set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}") set( CMAKE_SHARED_LINKER_FLAGS_INIT "${ARM_LINKER_FLAGS}" ) set( CMAKE_MODULE_LINKER_FLAGS_INIT "${ARM_LINKER_FLAGS}" ) set( CMAKE_EXE_LINKER_FLAGS_INIT "${ARM_LINKER_FLAGS}" ) endif() HM-HM-18.0/cmake/CMakeBuild/cmake/toolchains/i686-w64-mingw32-gcc-posix-ubuntu1604.cmake000066400000000000000000000023331442026013100276320ustar00rootroot00000000000000# name of the target operating system set( CMAKE_SYSTEM_NAME Windows ) set( CMAKE_SYSTEM_PROCESSOR x86 ) # which compilers to use for C and C++ set( CMAKE_C_COMPILER i686-w64-mingw32-gcc-posix ) set( CMAKE_CXX_COMPILER i686-w64-mingw32-g++-posix ) set( CMAKE_RC_COMPILER i686-w64-mingw32-windres ) # here is the target environment located #SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc /home/alex/mingw-install ) # # /usr/share/mingw-w64/include # /usr/x86_64-w64-mingw32/lib # /usr/x86_64-w64-mingw32/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libstdc++.a set( CMAKE_FIND_ROOT_PATH /usr/share/mingw-w64 /usr/i686-w64-mingw32 /usr/lib/gcc/i686-w64-mingw32/5.3-posix ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) set( bb_MINGW_RUNTIME_FILES /usr/lib/gcc/i686-w64-mingw32/5.3-posix/libstdc++-6.dll /usr/lib/gcc/i686-w64-mingw32/5.3-posix/libgcc_s_sjlj-1.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll ) HM-HM-18.0/cmake/CMakeBuild/cmake/toolchains/x86_64-w64-mingw32-gcc-posix-ubuntu1604.cmake000066400000000000000000000023761442026013100301030ustar00rootroot00000000000000# name of the target operating system set( CMAKE_SYSTEM_NAME Windows ) set( CMAKE_SYSTEM_PROCESSOR x86_64 ) # or AMD64? # which compilers to use for C and C++ set( CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix ) set( CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix ) set( CMAKE_RC_COMPILER x86_64-w64-mingw32-windres ) # here is the target environment located #SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc /home/alex/mingw-install ) # # /usr/share/mingw-w64/include # /usr/x86_64-w64-mingw32/lib # /usr/x86_64-w64-mingw32/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libstdc++.a set( CMAKE_FIND_ROOT_PATH /usr/share/mingw-w64 /usr/x86_64-w64-mingw32 /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) set( bb_MINGW_RUNTIME_FILES /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libstdc++-6.dll /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libgcc_s_seh-1.dll /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll ) HM-HM-18.0/cmake/CMakeBuild/cmake/toolchains/x86_64-w64-mingw32-gcc-posix-ubuntu1804.cmake000066400000000000000000000023761442026013100301050ustar00rootroot00000000000000# name of the target operating system set( CMAKE_SYSTEM_NAME Windows ) set( CMAKE_SYSTEM_PROCESSOR x86_64 ) # or AMD64? # which compilers to use for C and C++ set( CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix ) set( CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix ) set( CMAKE_RC_COMPILER x86_64-w64-mingw32-windres ) # here is the target environment located #SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc /home/alex/mingw-install ) # # /usr/share/mingw-w64/include # /usr/x86_64-w64-mingw32/lib # /usr/x86_64-w64-mingw32/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/include # /usr/lib/gcc/x86_64-w64-mingw32/5.3-posix/libstdc++.a set( CMAKE_FIND_ROOT_PATH /usr/share/mingw-w64 /usr/x86_64-w64-mingw32 /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) set( bb_MINGW_RUNTIME_FILES /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libstdc++-6.dll /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/libgcc_s_seh-1.dll /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll ) HM-HM-18.0/cmake/CMakeBuild/lldb/000077500000000000000000000000001442026013100161765ustar00rootroot00000000000000HM-HM-18.0/cmake/CMakeBuild/lldb/CMakeBuildLldbExt.py000077500000000000000000000010441442026013100217710ustar00rootroot00000000000000import lldb def Rectangle_SummaryProvider (valobj,internal_dict): height_val = valobj.GetChildMemberWithName('height') width_val = valobj.GetChildMemberWithName('width') height = height_val.GetValueAsUnsigned(0) width = width_val.GetValueAsUnsigned(0) area = height*width perimeter = 2*(height + width) return 'Area: ' + str(area) + ', Perimeter: ' + str(perimeter) def __lldb_init_module( debugger, dict ): debugger.HandleCommand( 'type summary add -F CMakeBuildLldbExt.Rectangle_SummaryProvider -e Rectangle' ) HM-HM-18.0/cmake/CMakeBuild/lldb/CMakeLists.txt000066400000000000000000000045631442026013100207460ustar00rootroot00000000000000# CMakeBuild/CMakeBuild/lldb/CMakeLists.txt if( NOT DEFINED LLDB_INSTALL_ROOT ) set( LLDB_INSTALL_ROOT "$ENV{HOME}/.lldb.d" ) message( STATUS "${CMAKE_CURRENT_LIST_FILE}: LLDB_INSTALL_ROOT not set, using default ${LLDB_INSTALL_ROOT}." ) endif() if( NOT DEFINED LLDBINIT_FILE ) set( LLDBINIT_FILE "$ENV{HOME}/.lldbinit" ) message( STATUS "${CMAKE_CURRENT_LIST_FILE}: LLDBINIT_FILE not set, using default ${LLDBINIT_FILE}." ) endif() if( NOT DEFINED ENABLE_LLDBINIT_UPDATE ) set( ENABLE_LLDBINIT_UPDATE TRUE ) message( STATUS "${CMAKE_CURRENT_LIST_FILE}: ENABLE_LLDBINIT_UPDATE not set, using default ${ENABLE_LLDBINIT_UPDATE}." ) endif() set( LLDB_INSTALL_DIR ${LLDB_INSTALL_ROOT}/${PROJECT_NAME} ) # Get all LLDB python modules file( GLOB LLDB_MODULES "*.py" ) configure_file( lldbinit-${PROJECT_NAME}.in lldbinit-${PROJECT_NAME} @ONLY ) if( ENABLE_LLDBINIT_UPDATE ) # Install LLDB files and update ~/.lldbinit # --- # Create a cmake script to update ~/.ldbinit set( cmake_lldbinit_module ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/BBuildEnvLldb.cmake ) set( input_file ${LLDBINIT_FILE} ) set( section_marker ${PROJECT_NAME} ) set( lldbinit_content "command source -s 0 ${LLDB_INSTALL_ROOT}/lldbinit-${PROJECT_NAME}" ) configure_file( lldbinit_update-in.cmake lldbinit_update.cmake ) # --- add_custom_target( Install${PROJECT_NAME}LldbFiles ${CMAKE_COMMAND} -E make_directory ${LLDB_INSTALL_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/lldbinit-${PROJECT_NAME} ${LLDB_INSTALL_ROOT} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LLDB_MODULES} ${LLDB_INSTALL_DIR} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/lldbinit_update.cmake VERBATIM SOURCES lldbinit-${PROJECT_NAME}.in ${LLDB_MODULES} ) else() # Install LLDB files without touching ~/.lldbinit add_custom_target( Install${PROJECT_NAME}LldbFiles ${CMAKE_COMMAND} -E make_directory ${LLDB_INSTALL_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/lldbinit-${PROJECT_NAME} ${LLDB_INSTALL_ROOT} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LLDB_MODULES} ${LLDB_INSTALL_DIR} VERBATIM SOURCES lldbinit-${PROJECT_NAME}.in ${LLDB_MODULES} ) endif() HM-HM-18.0/cmake/CMakeBuild/lldb/lldbinit-CMakeBuild.in000066400000000000000000000004151442026013100222650ustar00rootroot00000000000000# lldbinit-@PROJECT_NAME@ # # Add the following line to ~/.lldbinit # command source -s 0 @LLDB_INSTALL_ROOT@/lldbinit-@PROJECT_NAME@ # # Load a custom LLDB python module. command script import @LLDB_INSTALL_DIR@/CMakeBuildLldbExt.py # Other settings , aliases ... HM-HM-18.0/cmake/CMakeBuild/lldb/lldbinit_update-in.cmake000066400000000000000000000003641442026013100227520ustar00rootroot00000000000000# # lldbinit_update-in.cmake # include( @cmake_lldbinit_module@ ) # in-place add bb_lldbinit_update( ADD "@input_file@" @section_marker@ "@lldbinit_content@" ) # in-place remove # bb_lldbinit_update( REMOVE "@input_file@" @section_marker@ ) HM-HM-18.0/compat/000077500000000000000000000000001442026013100135245ustar00rootroot00000000000000HM-HM-18.0/compat/msvc/000077500000000000000000000000001442026013100144745ustar00rootroot00000000000000HM-HM-18.0/compat/msvc/stdint.h000066400000000000000000000007771442026013100161650ustar00rootroot00000000000000#pragma once #ifndef _MSC_VER #error local C99 type definition should only be used in Visual C++ before 2010 #endif #if _MSC_VER > 1500 #error local C99 type definition should only be used in Visual C++ before 2010 #endif /* a minimal set of C99 types for use with MSVC */ typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; typedef __int64 int64_t; typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; HM-HM-18.0/doc/000077500000000000000000000000001442026013100130065ustar00rootroot00000000000000HM-HM-18.0/doc/Doxyfile000066400000000000000000003223571442026013100145300ustar00rootroot00000000000000# Doxyfile 1.8.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "HEVC Test Model (HM)" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = HM-18.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = ../source # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = warning.log #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = ../source \ mainpage.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.for \ *.vhd \ *.vhdl # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = */.svn # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # compiled with the --with-libclang option. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /> stream x[Ko6Wk  t hnE=i~)ٖIv5!$|83ILddgOOx7<>byg``s9H 3=q?;CS#`!3D%xEeiKI|JZ#U51ߥ`&TieyE1IvrdJzI,ZZ`F뙅/$AvͤxiH63BIn7jCM% F3[ڃ^6s:E|1惮Y | iש|MUMZsj ˓֊#7옽Nt]^CBcF"'Gt*0fV﩮^?+&F.fد  <; ){0bkes←AF9ye5j"̎\z=fL Sfk2L5d8*Ӗ}C>#q%s Ju炋7|ʕ5bF }.|g"qkd GO`Wʶ]~m^.Pxn̗T *:1f J|W !M+BjUmMm;*mP]Pz?$f2|%b7eX歨5l40Q),tLij.f}?4ܘz`Q5+})5u"\x5n7q £l:ub!mRHҘYlzZ6+aҜǥwcwYe7ϕ?݋tX.435k!,ތ%Z?h p&,] פp%M09n0\2๘%_vx'$Sk+Wz38G6bWcjٞ1/EڰȀ9afxRkmF>iX^ŁRx@2/74߻'D/pAyٸ޺ g37ȬGL}[j1$wa`]YV!?jww0#\}﷼A23^H*=b):tt:鵄 ڻzGbIӶ=G|ۮxuWLJŴJˬm!D=g{hY~ګzEMYons>"ӿ{ endstream endobj 87 0 obj <> stream xn6} @Xކ Ȣ@[]IW]7$R![bl ( ;Y3wͿNpϝ0L^9a/do9M|-^$pUAWWkWW!~6~noؐdVB6ct7UձW'`Ü ȿ$Z 5P,h 2g%ɴCt'l[b^`ZtfE:HPp\lZrȤf>x t@=ha rpMޯ{5+˩Sx7e/B)^ʴRB`Z )ܴ~bVjZecx^((ud<zUTF̹VS:'U'd5b Pۇ5<&;0=je ?ܓ%t`e= ANKaB73V|RrMJ`*YNbY7R< fueҊ?yw%2ME&PWNa'[8gڰ7+3K莸fZ +`6k2;A]Ң"@ >-l>ˍVp]ӿ*G u>7'%P<5b(q9cJ1@W1yMr>Dbε૒RY2%Gq HH \aӅʬM&U$43@)hQgBU$j$.&.g \rl35 )LIj;(@HoPfgvx<=B NfV;z5TѬIn—Y,+ĭI'maKXS &wApg5)o+xeYLv]1$gJ[Vq*A84ˁj%w47X9_*P֦Vۨ. '>7qko,/&M,pKSzH/V(xl|ʉzd';Y?Ґ]Jr(ϹRF-tK}DT35FIiZoIH![+-Eljq0VP۸U1Σ\I*)6UR)ƔDɜLP^RĥnRs?J lyj΄.%үd(Q6Ҝ4E V5O-X&xr/0XºӲI6ǣ./}l\ylPAY$Q4ѝd-ndl K7Z}@ėOeRC-3<c_0<&&N*TS&5E8bbƴ'fSCR)E9m'mC܇I`PI%GorX-D3_O'l65vpGu ͶYxmB%1>tt!.i"α$}o#itcm*ݢMJT_|2[<^_QfZgt];h+v6j[[ؤ[i>;@10A:VA|t W['5` r8zW䏚;+W@:m ?sƈ*bguhQԢ5bZ6Nw}>ӿ-eVKC'-k0N6bFN6p4YbYEA,;,)t5GgmQ֎ q В8 yS`62J3c3NnwDnBg$?;MG'dܕcMټws< cULHS`mR!Y+-cЧD*> stream xڵZˎ6Wz1$@vn0 v6fߏ$Eɲn'AwʶD\DWwq qK7~H_N|\Yqjy$*^wBb6!LJۤ닲"iLߪHe{pzb"ʼ ,EUe*rﴺiuzY=f7X(w1H9pm<_Ћdϲo i"4hCS.|$7.:?);U+(ćr41@-byz&N U* U¤kO#v꘍&3(:Uhvv H3pG ZYWo|SaQoqQi( Tz#2R]5ܛ& _V.ntt?4I`*+gO.I92[7nٲU5z#CrGJzQ'E,qv] cR!.;#Eܲ}nQX*{S+GrwckGu].E)™׺x23@d:Y=g&G .eqƉA3S)c̉Za:wKm+OR,ɒUG1%~Y(JyN/4zm&dl ʹ1Becl|"m΍bg__t,\ٝ8i>MF 76&6Lږ,5Y%{vTyo*0!}2"zn#;iYDhY  b;(X&`DMrWf(҆@XmN# !fxc16Ua+k9D+je.சm`y1 pV#Ev5o3~ DLke3f>>K*g!.Bݵ\6V2q^)d7nt;9KE[KãgUpO99a,ErH*͑\mME2ՠA8 9wۀ@PPp 8fTu;kN{:lMc GE|A ~MQܮ>8lڧLlr{gs24oacŊC!va~yqkvjjk\Q`ᖡ z]P㘶z.>Z%&bynQqϒ$CmߛHH8R;91fj0N(&0r\ 8bpAviΝϏT~U&@ )"wS7ױ$@F.vhJ᭺sؔ6i'YĖ^J~8(N=Q*e(ezxd)}-7Z̡~fVn\6j*b-9nU?4HBDx9r<bQapxw- 0_lsZ2*]3|9:nn8)ߡVLK1O]wB+c ABT=u~?x!P:}aGpmUfQ#"2An:|5?R: [@BvJfZ^4[#xN`TO3 5Toٌ@[W Yz-ɛŻD0D^cOՍu(̸9f ՟b[#?}ZŽTwS06 1uAv5'0d"9E,t%rv^Ew%/DKbZ<9kOu c>μ;cm'ͶwIvvW=ر#;)O6D]1yil%!Iew>Wj5 HF߿,^spy}SUs>U=2w[w.U*m{w ߇ 0ɹ+z`B*aîVh A) Ë*-Po#_VKW1 endstream endobj 102 0 obj <> stream xYɎ7+Đ,.M@!@l 7s rȖO9HY&)jl.zEY]bHjM/׋//`1Z%r^5./k >hGԑ#.O{xι\y#>N:Iq=^E3Xg @3=TӌNo^r`њx]J%Ty8so=kMzϒ<ɌQe4:7 ,T9LPZGw_MtzYf)3/0/k*șz^L/ R t:<}#n|RUNFđ_Y˧q@J+(?3Ⲫ#QY),۞Z0*4E ȥ-}v)c-މDeNŬ۳Wz(⊀ #7E 6DBùl!<ӲV:KHB ?$2@Ah8Y t5t("g>qzVC)p>y} <VǙ#hO (hv[)v9UA?{wUՅg N~ܙc~K㢊]qE?LrҐ2M)YտݗMYUl!C^+$x6i*!IMD|wM2'~aKF_&lZN=iaUk7`sX^ش(I{,:4%i4Nx]/ f+{{ 9-=ZZ1JmXxNSF6qصYmuL]*'аk=aJ, ^ptʸ;.rlLd46릅!a:v+O%e@.^&w~(5sM^"6PSq___?cə1Ns~RӧgʝC,sĨFљX/T}reiL#yv3,Fsy*H)[ˠy[*x%v䪟pۀ9;ث(1?ufԊmviu'㮒*45] 5E ͪ$~s̾iIZ1ۨX; '~{[Y #nyߍӂ(T&(bzJ4:UuN$l=bUXX7\(RvenAiSࣸiPmHrfmcx/}x`hu[t(ה&f\$0dEwreފT/e^Up<}#rn΅t5{Y;-1G'BcUc0wс߄&荖ī}߉Bm镦m]Z2OmieC-v+C(=cu?&~)ⶐCM .P{K[~`CaiқJA妰5e:7-O0&_DD(mvzc~Sۯ)"1jUlpa0&7v endstream endobj 112 0 obj <> stream xڵ1Wșp(|8;{3t%`7*HQݚGYmSLjz.t~OϿM)ۧ{a ~/R*..OTҪqokTz!'$֥˧73Ue|g^q xlJ(8^ɋ6ȀXj>OU 'O鄩KBΗ|G 巋N+\r 1]^ j@!qz)N1C #|F,ziF)A"B `C1p\JIJTfCSbGF #!"۫3il ` i<=u+IQmnᗱwNyRpUe=WFYe}IŷM h@{Pzd_ 9?3%q:H쑑%+Cq-PZu9\)_/P^X莻N  9V~N+veg{2}"ʹ_1*!lO ;}sriwʕft~i6yZL{]֔,(g"re0wC-WJWp_wW3E*oVIKn,s}#8YZ_qinvGreVbaIղݳ2 |DSiJSVБq='iBlg,~18kg5ۼIlSmֵBPT6|UŞWT# ~_!h;mCO٘;1S ܌Z|ݩ*v~UR5‚d}m~J 'lJZ;>!A ?!Q Qcuʢu S|uq'BuF/a pQdfKCzbF6HݘYH0* Y1>ۣmz8=%Lzhrss2QbNOvק^7 "0 K,R eKO o_T 8s(i}Q*gRi d~ f,'&wֽ4ܿ'\SVk.Ѯ0`hh}۱b0 ܯhe@x2WPEa&yo:WkHLr6㌑"4toh ,S:5kAoΚj$.)B} s=)8dayZkbXksovڼ,=2j%,4I%.P!e\"^W!SAFB1,kV;QFG3[ҳװmʭ A1~DE3oBG[-;o_V"ZXk@A3yC2`KveO=Υ Yt&Aڇ^A@x[{hplY厉 _sT U%†v!}K/m,p(+(LMWJYϢ4ΜK:aуjsWoA-\Wkc/4v6ʐCeࡌ~E19D~3/6n.#Vqo@AFXٸ#f eop-8MnC-'mqN/Z(NmYpg-DZV4K=oEʐ>A"D:f<#'1a)O'A+IVSG5"U91mv˪ZOvqTC3ٺL&J/>?FnXnyfYρ첡6q6~t?B߬N79#-_%=U0/5w>(hEVRqqX pz0+Sj8Ha_>8=[caNЏp9~ԦIo4F{㚻E|v}϶o\<=7o)u=BKZ/~;^a5RW[*o/~< endstream endobj 120 0 obj <> stream x\9% +^\:cЁۀ3L;rX%uѯg ƛRI$E~T{My}..!N7uo?YԺ5۷`q߾}}]M&uߐ~}{C}緿U\%$B+-ګ.vj6@k%$62*lYg"r-ht7 He$g EeeP[۳G{(-IW-ӷbgsǼogj64j`Z{OO>|i{4di5-M/ۯ,27&,X7\yCƎf>.w`2I`e&ڒG $Dql>`쉌9E e#V:ё Ʊe&rnYM+6mW@\64^vwӂ7%\criԣZ1ӕ~[Y/Զ/-/tD[Hqt8Whcuކ,bVn=SH-`xYFJdALEcWރ@!]ZA064r2Ze_}GcslVO۾Txg]'5)[uѬeIV߅:"GG O^ٰ<njma/녵6o,#7ʳ_ 8 qjVd)0@HI(2tGB}3 8[a1Ps%*Tbu-W @Uy lŸ+nQ 2< b`OlCk]f(ܽK1@[^=XU63oi |..G@GTDfGZ48(],IsqAx$a)&_\fw(tW6p(pKLY0t6,aJSB09!d3Uס?!)`E29Fh܇=j\AO:r#H(7R8ja\H؅lN`2yir|gCHă 4I;DQxRGI]:knE%r2Ud-V:uK5M<-3@k i~4W-ft5(MhgnWOs8$3rd<[py*i }Ǜ[[PsBg뷎vH1=4~@R xdM |eu܎ʼWȮZ6=V]-HZxC5WnIBhRvڳ"4cWq 82ا֧cwOXЋNJ6n(IUDva;]([8QXFEsD=?*SBU}nQjَ"V _'žC*uVB Ix`rXr%5Tvb`nWN5xܢ]|Zgb a}ս ۢxuE}̇4I`<9kwJ-?C#^VǸʊ `Kȕo09Yl1[h̥PmuOBARK7ޫO`P#O" E#-Ȋ\B4^6Kا2;ZW-.Mlf yHyJ]kcjB$'JhV`6fu*ʕ> *=dpڶ{W=h5;fnyd+ g_ 1 M'\q"~/s+ Ty]LYStN8Y lӎ9Dt84~Ǵϊyf+ZY5h.m/ӕ{W&UFbx]O6f2xDS .~pClCspZhp0fJc{Ef)gU(TjѸ`BM Ziu p&YQ݂&dњhEml,*%.3 ;ԍuֶ֞#cC+ CMBatuzN‰,w-y@bXE/7},Xި-a2h+N}w34հڜVBpYum>EiJ_I㌪oJnIw,fOZVRCk(4Ŧ!ڊ@abz3uȁ Dqp!7'Ĵǜj|8*`y~.Jo$A ]Q4Ks JRhOMma;@MoZ_vp\ X:?p,=^"9:lW+U uqx7t @o."I΂x9jm^` NZbVkDdکZ=Z7jqviZjjñf]Df$5 @\Me]5yޮzF7C߹buX'/<׉y08dm*' mG)&^|PǚoG=hāi>l+W&X"Iw$? O~0X%?Ƕu}S O# K ~_Ȝ}]}ʣt%ҏF}}x G!k/-1`uqJw'4%҇~eyIf ?.Sh5;o\ڣe?JZGX՞Zr=9Ih}~i?3Lry*q0ΨO]ky5{YBY&q{Q)yjGltEOZ7)? c`㓍 zT@ _l CAtxކM{o>Ѵ'jKr푢^Qܳt l`M$W GqnEPJApл%<_:sgm>4bn~wvC/`Iphx^e_K8={l:> stream xڭteT\-<-w ASPRkpw@%ӷot{l.[Zl XufbA\4avj0!6M YχAO/:C`P3Xdnn=@fr0h1S`s `xqPgu p, `[wj&y5< v]l!9fX sӚ3pC`?&V=8,P8 Oz _;ž=m`0'g'sG39u:[v<0gOOKٞa@ vw AmϹ!ZV#;9=WS2Y9 guPs{0l1?3 N\Kϐag;bO}Avn_975lM}E0{cÖvb[ƶlroZe&C(_S*HC&(#M6oOIBkAHD,%E\K,U-#I/NɘJ|~ SKN}r}jHA$EuvBܺ/BRRV}$&WOqY_ʈh7[(\뼒_3I_uE1*̦ϼB#̋3ɣ\2OudBʐՌ3UevBO7̅L52KL( AA\tK+sV;ex*skv'3t @1aE$zFF1h>Npy+8,qk //<+_x0Z~ $qp ^ q{&b݉kqZ%?ܚu\$X% mb͢}|)hL|E^PayؿKܲ;NQsI!u 8y4^< tT7nؗ$NO MRc֐$@x jБ(IYڏv Z: L' ɗZh/zP[+8NNN1X('rg d,Cj{TdAgmo wI8[ #w8ߟm:F0Dnif/5.1(i)a"^,) :I޼cy)jx,-5Hzu 8_f̪|e&QpK6m6WcFZ &M- ~b$pN+/? UjF빬{mdP)7Z x>r>C釨Zvi+VҪ<ypGI$'+J>y]!J q4) UG*;U L8=X:(8Rl:Rm]bEO|EMita#m;5kя x#Ӧ+)M-Pe"MK{ %He ym|Ac'}6/)D (fsEaΖ ݵK3yxDBgP.;/+oDe|9sA'Gk䔿Բ_?6kR}C,7|iR=h?g`jgjHC%;<)ɺjVB*}"(:S"HZQًPVKuaQ Ry24o;vHÜ]uD˅bZZ'G]F!"&aL }]ڶY +k_-h,&_%5oʐNYw_WHSeG00h!.|9E8k6n%6Tļ:w_kYKދ`]Ru~"h~5&W0>yw&tYb6|VZ3g=eܫrTM4j|. @~.#y8``iG8n#{1vYtF׃WꭥFwӯ99YDEWH ո=޻HZՋ"zW1{2vG*F' xB>n_IG&zLHd[nH\xS*3{>!o,^G>j=!Afn mKmJ>.+L>  ޺2n "\vsdfU0#x& }@뭻+0>C+pdWp/>E'_Q\pscQ^~},MgUqO3Ux  ?WL >]ifޛ Ѥ/ɲRF`Jsl&p &7& 2=?"6N!d&*Mt_Ҫo}eLpH~`Z|x)Ih uL]0묎@To \;\K#|cXU ^릪]dr3񛆛PpA_@$Iz.קܗR/%N|ɳ2"JPŊ,V\~RY6fu(p .=!}ly0P 20:n1Y^YFbaD8UC6=xFf.1?ዘZh2Ka%LǂY9kkd][o}ν˔EvD٭8[ԗ82gT}12C1쪩E'eOca*Mrdo|iRX4DkmZK<3&kjްӐ)'6:wQip}5i2^ڢJ))C*HF6xp~KLha(4Nܙ`:ړ+LEǤRT{ 7B Ĥ4 ۋ?ef- ]\Ei1lom0- p 3mN .ޑ^X|ѶK4|Zi&HN{7A%i^(ۨI .Gd_ۊu -}6/'z4uӴroEҎDߋ7)Ѯ\Ab춑P"@:uDrm4,F#6RsD5QYo Z+,1+c'IyreJ &|Hni} ghr\Vszkz%cW rzf`VB~G'ak;Sn6G2fc8Hh$4L>L񧃳5X:pTtq"^Sia;TέfFNrAĬHя JsQ}=sгnlZņs}Ҹl4}c& NJzqh#QG^nЉsVcIiJB-Ð{|4| qAm3YG?@g&CC*|\[JTIʙPdy^x ^n"ln\' N힕OiT bĤ\IV\}iu _VB1;Ԑxp4?,} 7N=0?H_n 1țsNx'V !M&JֹߎUyv&i5OnU.A/\ ]SJo>xߩ.Q㖚 9l/ +yXaa2wLk=wpÃw|$dhA1w[TFK8ʕ TE?.N^ Y%jf*򔽴]5;tetAYs\l+r$ u)?㠇s|2ZHyss8NDz|PTZtW bzBg3AS\EIE|k!koZñpӵϫ{ч;,{>;l}6 0 ?Hj?DǜkQeY5+p>4aԹCc:|ƄNm cB0jo,ADTx}ơ@zN =+1/]?UPj$-qXwrɄ롫$b<*:\v14v3]f ‚,ʼn3Am aڢz[s$(,ӟ$JMX@ΦLvVsduPDYmnZlabU/mvib2:4tJEl@7ܹ"Rx>(W XQ9Ob0ҏDU/P*O+AiZ|5{=WWRJG.N(,{un.M1zY5l:j3LJF,uBR` G7Az!~ž>($<7R/HD5BE\AWwEO^%(U%ԥDWa&B>{K9? iH#xrA]n=E A^xVRK-l1>t |?a7ɮEiAL>!3߄5yI67ăDK3[p:[O-{Wf&z َ;/O1:XpbL{vwmyѲjz5 YTwǃ^.G,A #z7A%n(i?ghi "2hcCAGOF=7ܗʣ7,AI1u;MJݐw. Tbϼ(n8z_qBM?J:1I9U)J1x U'pi(fJVʭj|<+Md&t>^}dkKӃbrW']|IN[⴩^ύ+c%^!aB;ƫk9.39*J:/cNq$Xv]%AyT&3wq On*uD['#uQ{K΄,@Rӧӛ!djȹȇL^{km$i!{>c,52( $c|ga'ɺG7E.z(=fVbrfJ~'},58{[fxn~)1B/-h!6f@pr ӜGdԙ6G̘2k@ \ׯ)@6 \A_BN!񃕩B}zeD@xGʑ U< GeS_}͐RքJ!`ZRy[\"od^[xy~!>^sA5n"h6WS18a j ֐Sb' 92afmKI/)I ~o$A\9-֜Ι䑒tq eLznyB p{o4mlFyoVԝo3$&hmxJ]qP=EeZZBC~PM ֕uhA:B|;aeNCq!H={i?0e~d_w/P퐄ɿV8k+c b[x4ˎVAt2fա]#N2'lgsTS5ZK!qb&²wo: 80!X%OkH Ceq]{n[{dEA[#7ErB5bKc4Zbv%JP!L]vE}F`0=O923f+VSn %á#]{ Ũ=̋kZr6Kd 6 N?Ww<s[__֠>Ft?߰O{BB#[T|PyRͻVO |cl>i\TW<$#!/7}JZ5[?΢zh[>=S4RS;!m_^01>#:zp$cbB,+F(m̆.A= SDH.̇O 3Psw/~H}E#2Ee&cQpNay\/ܒ ~UC/C3U"֞5,L2 \D(l"yBM8%MD ^~59~_^d@NzwN蛀_Y8V!yKhsLh069qo) ŜaM}67dAs 'T'E0x(oaɔ$NousWْxXQ|"bߺ W[py9\J:_xe@(I3m_YYܰ+VCM+SY5ѻV2RKDͻ>0siD 2$q|?ؐ Ӆlˏ1c&_e)>솀o rp.%8~x%$"bd1GWjQ;,Gm?4T& endstream endobj 130 0 obj <>/Matrix[.5 -.866025 .866025 .5 0 0]/Length 21/Filter/FlateDecode>> stream x3P0P04bT4.U endstream endobj 131 0 obj <>/Matrix[.866025 .5 -.5 .866025 0 0]/Length 21/Filter/FlateDecode>> stream x3P0P04bT4.U endstream endobj 132 0 obj <>/Pattern 129 0 R>>/Filter/FlateDecode/Length 778>> stream xŖ;o0 w I皾,IۊNIڢHP4K~II?AbӢğH;%?BI#vZtO *bcS|nG+hefdwvuV! Axl9&Yv LB3HsJ١Y y"(L2ɨNK.cr'C71JH#NˈTfa Ji$I c,,`A+7p=ƌSCB1lzeZC"I0ÃFN^fY ʃtȍ)!p& @1ubM$GS!œk`@1X|XWNĊĊܨ3" b~"V NT(M7NĊA׉un& ŵXHcE(zjR9TZ 0UcO/=nW|Tmi%S[*pᮞ j2Yo;݌  [7l%o3qbK/qWn0PZtܱ4cUwWwiA6UYW:W`Hfu> stream xWXY8[3.I{&Fp~(Qhk0vF#Q$7unč?qfgq_zYg{qIˤ͌s'%>io{ߵ&<2TvQmg:ײQUN#@z6kx~IYݮ> -%nrUJmXvMb|K;͊WlE<'HCJ9%[wQ D 6SgP(nґ'u۴vu;))דLIMb&6QCZ+a8er"S^: 'IM&Ղnn O_L\$;&I<  E ᵢuONݥ^]"֮v]Rb&нCV6vuƘ8*`:[[%uc]6=& GRky#I_úYG'xIƝhM$V,D+m $p(_~hj'0oi^Ϡ{2hĩNuFT =H.U7.7 rWd瘔" Ӥ) ~O+aHyl\_TVf?jɩՆW!8f }rbQΎVҥ.HWY^vNCcWf*m.#\¥3 Es-J3AKe|{'b}i(4!o᤹J7?d1i{nG:GM HeJQNVW+'afNw(}񩓾8hP-uev̤pOiuKob.p䔮l[ qkh½8&([boQ~-[ن*iͻ/&/w鰷Ю>80i޼#~vc:d]͚d/1󪳈u myF6*GXI:OJ#PV3(˞4fMcդI:;K 1 ^?CI c!zI Mb:I2!:r0FŽj@ jVz EHDQ3 "j+bcH~;?/eȴ's{_V+QԒ?W _ Ҩ2>1,7[2|!K4V0MG+&.uyygq ŝ{L۹6J8 @ef[8mŦ)ǐ`( S_w8%P)$${ËӃrqdW9bp%-̄ğzL$b},P t F#( cMW&\1k[pzDGԞP } -Y.h=n0?J$I~LϾ?ҖX3eR?jb^l!?NJƅ*}b8fձ43%X4hdM TBx TaN ]9Vʔ`7Sz |^ōCS?e .& 9[Bs9 =НAT %FmDjk sLuŠm>eT#feI=Q\˥%J#CJy[Ң=/A1BF{ .=4*ǜA{;m3n6yi˶634**X.=&a^BExjnZ<&M9rw0 Uz&H b$lxÔlhFPxk1If;GlyreL;bt[bJ>ZMw5엽soM71UREnRNj4 6q396x0kjޥ':Q',{; hɼ < ~woT$WH1>|Wzҧ)(wI7h:Z~-{4Os`Ic[0=gXM"eYEn5L ICV򭢶Ƀ=QAYQNh06=#pgbe\IlZɒ,2vnc)辛x7Qҍ(tpڏ0?pr{ܞޠ:#1]L+m,ƍ(%8F Dh.xN`cx3# u ½~qcn#!w06I\skZxT$z̛K*:o 1\PIg*o<S/hr endstream endobj 143 0 obj <> stream xZK7 WqU=@[AE`{"A{ȩD=Gc;fQ$ HD~f?XXol\Zg{gѧv QZU ~PGpXCz(t&U6B^uȃ?=>r@3{Q8dW2)ѪVM'gOIL.SgO([δ1c[eO1?vr70?[o6e:|Y\× >jd7/|ݳP~ 50fn$-V!!LI>}$oX wxD&Z2]Q"a4 kR*D9].Ir\)b9y[%JcW3aa(,Bof ɴ)ENKθvfW9sČGvh1sjX!FC0emja.a˼dUh _3kRV4WcnO|36kVz`Vܷ3p=nZtj;Mi֪j'0mmXӑs4H{awjR|M- 'ݏH/iO!?@՘=]E\L3zъAb[vB{}6JyN{90i|JtXJ> =11[6\z"\?Yxbd`fVn2v>0=JB 'aNu;--hTm)Қ`R݈X#0Eۭ=f[3 F:v,{̇n4ۦA3F *kO{MGrd:i5`d2{&gj5VwR&wGӍlp]iëW[v~Wlq{SH#`2ܞ䶪\)?X B|Z~_~._B0['3$Jk2ػW궈R%<|UR,S~$)$mw>NN3uEr?탪aK4ҢYɰ*E:6{a`^A#=)bPwWjeC=~Pv_ˆx جO{_X4nP6 F}17?L8/ oט5X5 cְS!Is9՛ rpʭ[PRB80ʾ0 Q`z rP mo!udݴ`rXYf|9y4J)LjfN}btz4'Is"3'j&fxA˸Ya!;}a Q*fU_YB9Կ31ޠ3v:1ݞ}dJ)r-ad~~2+<^Up83 x^p>0x>#Fbܵ+gkϐ!2lS ]yGKՑ3u{4Z5ni'41bb4e[o̊:OhN>ۣ^8c)2*i`nʯ%//R종zHK V*};cuE{&U*Ie@*깷0m7L16I@Xoyٰ )I7z_1;F_;()P[,åE愗^y~8~- J(5铵n9ݿC'D endstream endobj 149 0 obj <> stream x\9c+^4:05lljȉ'hyTIV60=xU_$|boo?Ͽ|~o^k}n'%wnݾ| c܄?뿿}뗣m?p0 i>me$- %*'e3igg }_9Oy[+{9a_O\<ZƲKPgb/{yK \7Y0Ho)<*U|M@&Qp$ª9C>v~sC祧ypTWyQNXEkA(ʶBsΧz(\x$Y rҕTI># _C;bM(uR` ݊\q@0\Kefmۥwz=f;i+ajn~}G۽1*톋dGViYz#<56 BVPqssvuTbl%Jd8ROԈa [ݦ:~wE~ʼn,:S 8O狴?V݀ n֏|nq[4;Jq00)34j:M]VuØA꺘ZbNlÙsKcduP6iW`6([IsvX_}KヽKk%-גypyp$OM9ᶁy”ELV,MSQufГX=7 BZb>莡7/O9B-bHY7sp㣜q5Q\2]p+I}4XjVؿԖ2"NdԢҞRٷ#{/5dmnUvҶܼ߆H#16WbH DW&164J}}NY?jTtS^*so<蘌%2v0AF|Gf`:fNQPjpy7QoJ|(%3JwQ-EL.,jY^e.P jp?V4G7 ?)ŗb0kS|%³2bpE=y[fEub Sb}j#J&G[ƒQ%+.VkUd6OUւ}C˥0ZDeu3N6 r#I7Qү˹C)>APW0Y&&b]xl>ZS貜Y0rD, |d1d;ƒ|C~D_IK X\wzܓ;< M|?%yN*[ym(Nta?Ncup1w  B@#&/#4!Ȟhm39X66gĂ61x'bH$ vr c]M(riSU7;M[zCPȴIыt!/a.@ۙi䱽q.ҔGz I\&܃EXbۼmӒy#kJ*t͍tnбR0@5 8cl}_yqg -b\.ٵ.4Y&?21t^F ;T/K^XǿC)}H"T$c]<~1cCyeo$.mvp.I凒T~IBH*uڕ2+򵎅brtm$IB{{dwj[р?V?`gVm]ڳ%_~._n\-%Z~a\/6" a&վƯ@]_)-BҚ0y@>_D^i8) ]@"&8>[w\{>|}8fh޾bT/@=Tk/Ak`?yyZ6/4fIKs;䡆Ѡv.>4Kɼo6JW,rh̄f*H󔧥vzޠ.(I Q ôa`(Zd>aC` TZYA0$C1'OZ~?M}4YHw8%A }_? endstream endobj 152 0 obj <> stream x\;$+& |bos0;qbGU&{zvW,ᰘ~:'gc,s/W'.a r*I%uUنu3YT*l{{>+7b۬z̚jbq4%i<#2=MLVAk84e!p5k e/98iQNgmiA~'j9q˯Y]ŒЎқ2X95p4C!0TԌ񰿥yAIM8>C.|^EUg2zR%$"NdP,[OC+&B~3SzD!*TG4B+1YUB4z*^ܟFoG;桴d`P/919A;C+`hse!ށ>YP\HT1$)H KfR3C"ԢNnF]]Vv^dLvuU67O!RV~' a <r߹ܮ2g2Wl-֞9(kHu$Ki(p S#n2nkɃP &X_#Ml͛J#}[W.*_ɦ1=VY;y?dva1zW !ځEn^k3¶2֖:h>U-3pۍCPn7\NٯO䳞7}[Gpa8ظxcs\E' j/j@ˠ7q}cAo鉟 4R`c>ն%,z(xȦw׼w_}Gt,cVTI_qP,Ԋs+ 9孙;rGAkLjET ݥA(P0YkQTicEbX)+V`Ա]^734ba+&sHA/T,R*M;8)(~ߓW0L>te8L]MJ;#-s ة7.) C)iHiiH 'J~XO<<(e`FҷB&p tzY?k}bرN85l:E%n<\I%en'!*66I ]K*PޝZk||0hˈ4 2C L<#4Um ‡;Pm5ݧ)rMδꏝ '\Ңb,t_pM l%dc ;0ٞ~1R+Q<ʐ+JruoYE4K϶-<8 ^ nco̥wVA KK"|;E@ DI>VUZ=GBt]om Ucߣ w SGn~ UJ} 5ʺ9Vr,%Rkf͞NY@vպԍ9YgU]reڻQ(!ڳ a@ QI0_6r+~RЂ lcE艓 QQ0s@47 7U4{q #Xǎ@G''9/#BN^I}DȕY &ɯgRf :ևV4tI_ӿYA'"e` G›}!49JȮQOa6_pUjg>n:kKaѐuW,]_U>/y:;isblagL09ik-Y,'^ZzWv}h.ߕCB[#B% CPڍbw_EO ˷=sD<6mլAO;%%2üV ɓf4bdP3E(M,Ar{)eG'=d<س#:$:eg|X f>$n|}aCׯ MX-H>Z|`)jAu Yo_imķrҊYCayZ HvZOA`ؼi"l uYx1<>}4s#TRkB.PtG];[Q y{(UA$.S<_%[we/ o)%}35ܯQnD+:Gv2=Z~iL5Z6i0NNM<9K޻.ĽËUTϺAx%)oOMeZi'G6}iɮ4hw){M"p7 gB*wx=Ԓ6IZ :, 75*'#:ѥ8=&sqd0wE~>6ØVkff 2!IٸO'U]hLgPѮ{C±l1C/o #nTdEǪbR\O'%BEDbL &A~`?^`ឫ|/fEd7ZqLԝepIr\ C꥟]E_P YM.kIrZ|r_׃U{5j\Ami;} &dF&r葛{[WFB=ٰh5jWR>֏BL1W$A,io`r&'OYOm#H//rH'<^8+o*5! endstream endobj 155 0 obj <> stream x[KWq04dq܌afM؆mE&{zfG"`cǪ"{ma bb#-}ӿ_,_}'F-/P&oO +){?|22Bĝw2W/hxK\S5DQ =i)PG_Pcy4m2|Ϡ!gpA"p>'=FB5:u1qc2KE,a#E]M(;4XFtyUKc&je rd"_A]ΥNcϑJ8|=^}2yoJ}&LyNF(Ɔ!2(U=na=GА(겚\olxHj|8%Gؕ#ZBqoፖPSpIPA4ēȳ\%8y1EW\kJP{yq{ˤ$Tp*- "8ޯ֕tsBivޜ[RN 䖴~qPqY*# …)<MV[/ُZZR!0uO5ӑm)P{wlmcCRYb}^Y[5u5u&^[ώg ݼr<ޞ׆E%Y5`+F6bSR]L1Kν%dJXn]Mk[E0zu3!3juԽgSz0303k(t_zmI=^e^E{N,nm[9yhm*NMeWipLK&P|nU$CVFlW3V' %Mcz.Z]J:z+gV+j;>v A2vjҲ[c%ΌZ-67FgQcM%LD}XOUbK_g4dJz".CI*6%rk4I5\PP<(p8y1/#=bFtem,%YAcS&6 M䐑yAGܨ;)بiffFب}n3KfE,rfUJ[[i c25ݰ JY1&Y&=d NGY%ґ% K,&s`OW'l?7Edy_ٲ3[Z*bK!{8n4p(7PTiCAЎ?S{S?aắӫgpY> /YrrJ_(UyI2wK\@;m9:vVRx=fC/oܠf>Ig8,;WӪiy$) Ɍw7 L8FCM}3~ixs`kٮV~L!x10D4/c~ǃzx ÿ>|K^2[nC!#4FmKb+lsE< wZ{q;bzCp[IO #oپ3=9k].nwաY#ꀇ7UstPD7lYxʗ.)N}Iu秓ur x8=9z0VP8)Ccзs_~sRRy|`}֟ KÂ+C eXErKN}HnE@=¡nx=Y'FJt:D<7 g_E7VUBUK1Ds4D_67&IŹg)[F%$ qRoo(bĞQ> stream x[IWQ:4}&}0`ܢK\Oy\XEVFfq{?88;4O|^~Y-X_!9u fz'ΕZ>z: ׋R*_F1O)`R4g y}†2ȀbJD HlY3UHr"7ݮ""^єP)|w_qqL{p)(zWƙ#7`,`뼃h努}ـܓjS(!r LG[zϒd֔1wPu{8^ Cmd4fH&O3ʏ%5F,ӧV8X[>MB ub=uLQٴRU߷2 2ȔM8xhB#N )2BW,\nBڢ٤C'p=oeAO~s}qsw!}mƼ 1fHlzxA.Tp.όtssXiT%& ({<7tg Erɜ0ǦC $7ؤL^4l,kJ1]q[{"I.h/2 >ZR߫4㶀tyr 9+}]!0lNԨM-z2H;H5b [S:W$́Hk#FA =H$e4Cpi:Ff̊XNr9? % |> ޭ%묺ؓrfힸoA:r11yPZӸ4L/r=_+`s8*0Kv.tUT yiQ[b!CMηW~#zVEs [eiLIҌ} ӷlz$zhݤTS1/#[GCuvf7LSd,kZ"NTU++cbŠ:z5m3(IUr vu/G(*Τ4ǦY!j iBzҽ1Pr䪲0xI YrBN1olkځx]+0nԌշ(wCDыX ٗ+u" A(^V󂧝$ ;\gLBVpT$;3lE̾H3z! ]F  } x]^n5n`,WfuC>l3FWs7ׇx }=$B6y?FX4F,  73QѤe Z:ܴUex[yMmz]!3fU%6[9=әi\wN2!fa4I_zW4Qk,PF{n/i`a80!sB|n} k6iw}эy3 D*Hf]5R&|^10 dEd"tBcL^Rq] I) J&CSL<j ՛#jE-k[ K:I{XHgJ(6UͶ] *LAҸ6 _Kq/ l .6FZͭAݸM郕v5zeXJҟ۱mZ֭vnP)%J(> stream xn%GV#xerX"YdW/AnXY~Z?88|N-X>VD;;eL%}I8</| v?3]W[9,Q(l?#nqMru1@1fZq7"d ĕu )2NڅInýUKgMG*iN棛%ڡg<澘8e=$m5EKZ0Vui#\I D8L:`mR`?Үq&F`fA٩ m:(kF+rFLG$;/'6[s+L-uCIpJGIm)&KZΉz{S4-(de~n\Q#b\52 )a "80Lȩ,p0aOcsqfBSRh!b 1H U\ ر̕-7"0'M.6Qt*Fq! ؅oRi kgE) rGiy (jJđc> nC bfW3˓G]C;)i;4+Z:-t5ǔ` d/߁RCV&i4D=`a4xh# Qiarm\nWK,;osSP`pr_Vl!OȑjW $V9m_29]rSAmdKj=3[ܧs;GO*GMH͊P3QTNqDM ϼis49&7T7Ă }'q =] FW#&a\xbJZt>ѬOz Y>5JzC|@8 0qpܟ&h+Ȏ˧@V(pTZGր X<OQBxY8qy vGf XqJ٨orjv֎!%ʽ }ia2Fd&@] /!ma>绫@GeAr$&BdXE H_#%vHS/P5A ~4bG gξ%V+XB0i^ V2?ӈ.wsǠ0-ݔ7\PL6ɠjX!%R23b2T\>. v}O$b"+@CuߒҌ;B< YҗԒR1nhפ. 0mQR#F(yӜ*p{haFB[8UToًe^,{ˮ6kWXMa \ܨQ;"`2>($ū t.)ӕ9ߡ%Bi;mRJ;dQ c"[28y{Q**٩F>jSu-<S5ct1}-ǘ>~I"e D 9)elK! <տ뗪 婝tƌ-oJ4 hu.$LU-dzg2͋# I(W qh)Plꝡ ^iFr+,zIfJZ^n)-,&x Mɒ{!12s$(A0dU͒U+߉PMK2@sB9>j/Zy^Ej ktԊ;FlJO.] uB#9|Qxv,DWGW+gB:ӒtyΖWY^ c,I6WLѠɅ0˯6ºCnu+or\3RsѬnRÜS88Nī="Xq0BYlJQd7dQRq1MٽOeuf4<0D§ЏbT;0)kn^hfOTWE: Rq.wW@-hy+,`Qs-a᳕rsBQEi['1rPnZ~VvhwԜC?kCY)dz1G3l=jK.nN(Z'ߌ[iI=^ tVlR] _cckꫭ+9✜WsEk@@FiAIF97S=Я|[ o endstream endobj 166 0 obj <> stream xn=_K;)>8brIDKd$YRc3=uu]=vtG?l]ݝ܅߿_}(Y,t~G%]*/n$+eݧO{gLns?֍&iݍf!{JtWOgHM./ӋO[#w]ѻEX{ MxzQcQb&dV'" w"#uS(q(K6-D"Jkp}Dt6G~uj7-D^&AR/,P-s+q>JNqTu Ћa4* d<y@QnPWe0;O$WRxDF1 #QV/nIXY$ pbmĊWfb Le"D| R8`}{C*B I,DN<88%ޏ- 4 9h=yLĴƖ_EVT9<3`$ֆDc.xG2MD3h%.ꌛn7^"~e󁢠+NY5~XJְqsbycbӕtaeY2LmxžufH` <j` DlZ{lt'T1"A6@Xiy#Cs@d=D0U CvPΟsLmVC"]YE)UhKP_L{t93a;P&?@0IN/Tgt&h6$\{`vw6/bC9@ 4Te3FX4. rn& c*:)?:|8TErUf%Y3ˋG@lο-SYi  eL.R"+Afٷ ~*>$*9kޭ*%qaT nMѷKFبk>b5PM Sb狃6烕̣}$}`1BHmZDgΩ{2P%+[h/UPePT̊qj8b٬6.`\~?$Y `:#P߮ki݀7E>ZqJ~5^Y(?"u1ICte#V)1_BPu8H=\CL;D˶ u4l`h$)UYw .Ǖa oSg#E*\U2'+lqʰ;\0,nӋ>ֲ~]'5Iƶ2"l%̝i#Dҁ355 J/]/|~Bs~a[b/Zx@~y/DїiKy݊X_C'iJ:} Y(֬އEeg)Aޚst"ԜB9Ȭ6J;7i zB#!5:!ݤs>q>>UD 9ڥKe;<S'8dHBJ:%sq~FTO@>ZSCQAf²3 tޛ㻻R!Qd wMlC۰9uQذǼ{0WoP">!e//>W{Y:g,oA*5*U4' dƪago1T% r~hH8yg`7h=`EA/56X5ȵXG ;*hoշ"ڽ:)fmO-SS6aE xX\&+@*(f2k=u4U]n\sQQbsA O W u9BX6()P|*WY=x2iwqiO#L՜ͥ ,\+DҖD& >I}!LHK/P:hmۑ1j+"?Φ)fJQ5:hqT>zJnMmF*M Tt.GgY~I$IEڅNxA5u:Ly[xB!DaU:WU:_d7qLy=ϰp֙xnFDW7K(BNJ.],F..B)C:M]LM0 `CZ&n!;[W 0p#88|7WlztGWWBC!MQ5eij|3OR1{ߤ(Hl\VlճVZ[ob?F%QT*yg;ppp2\)+Yޫ]!&!P?ƸV)oL"*DĨf$ ,"`Y!vyNxqFUᡕڪt`iV U;Y :nWkҫSRJ8UyDmIa%o"@+B|.iOiT9#Va t]}:rHu%ÛUr`ҜHϚ$zOB ;띲BoJlS1])՚\U`m HMJN%m-\T$yiwSuI$X NUvűc[;&Ɣʹ&͢hM=7]wOw^O1$LK@I*PH.UyH1}g߉p59/)8Q&ם"'Gl5V+n\xЈOcfqS쾝QvMYHa-Rwa.&&f{qj~|K,8%Džsfd??_yrI=] ͥZҥ |YtK)tK#qH>_~L8l6K^c9{[)Qbf +A 3]nSxNSDBT;TNcQ92sxƻv7391q}|'aL>O^⺺s' Uǻqn{ vj#G-7UڡySjVQ6q`^0OfYDZ{xq'Mm}U @)4Mz +|cZuE8KLQoK: )C@~\`:T%nEA12ˌ5[haN].;VIB8L3^ɐѱ '8|v5c=/UIl6jj;Mb@Z48blY=FֽAN*>38GYxZ;gLx%*?ggaLczYHT)<I&fH4Ll9.yfUItV&'8eɊ 2_r! 'K[l?a{]*\kMI'C!ބİ)F$Q~>C*Û7N/jw7?~a4vpjN]#z..t9ׅ2 %&:[f9EvAHmPҭ0WTaBK355D_4h+;xNsҶ'Tg[BM1xJCrnPb?In36f:#R%Z1_;FGx ׎Ƭ1o+8*_G:╼jނ(ip6.Qe50N-d`\Fzd"@fnIuN=n'v{4C:7*1.EPМC'GJj'fU&aC;.;6k{R uRGQKo(9jN_sXTCs S;RjM<.>W@᪓4WǤN,NVj l ,?GA""o%jp(j{/UYi8piNgV^*[c5ӋǿeL.wᄆϢ0~.`IЛs_V endstream endobj 169 0 obj <> stream xˎ$힯crdq܌a7K~$(TU=k#(T~ɛHͫwq 9=Ks>޾^ߤآ&bL̖ }p1oLyKL~*]kǦ16X+ǧw'VYV[:-> `0%?x|_oXm1nw7m3~vOE:-:g O3f$:*@LK80TMD 0܇Mpb\-Qd [6HOV8T[0]M]M688B|?'鄿D ܸ4"c لKL#dC2&쌩#&pϹw-o<;#'pw%¦ID[ķ6P`‰1{QeZFdQ} (_=cǞj҈mn+/ȭHnYKuOe]9֔y3K[ 4 `C2 ;f=nYo$MznpLQe<0ҩM{MylThrhU)#;ъ@#7ćՈ)8z ޭ/(b1ٸ#lDaַU2V] 0;4)_D9:k{Q-Cˆ=G!@!Ma[m sO g Oѩgy>"W qMY"fIFlO+ڶ]L@{)v;+ߴժvtL^i:)2j^Vi"' ]hh;Kx1KH\=G x-pn.|W%mvGsRX_SMAL **upίp`ϳ|_J^QCu1S$v(qNs)-Nn5Vz=ЬxQcLVX;gz(7d(Io )XL(R>xty4_CRm.O&pݰ:d+XgKZә!f|jr7NX9ֺžTP<5#Yz~8bH}??.Ƽki;rG3?:Y̝C/idQkʥ<җnjZd,xvO}SN~ǝ2>N ST;q&87uC"S?@|xH"K,0"8?TvM9 7# ƣWZ+fzm+iVS,}ǰ G*5(P}x8BIjӞq 6>*^K+adyg-]dn:&iHlsʋ>]v}2rZtLr3jXIU rOwLc#Kœ2"yőq>Kw\N ׇ, ju8s^VjB ,w;ȣ ;>$2{3S:t4ժ&T\IH%h38tZSgD7#ʪ6nf" =zrr8jqr321ʯM̪H27kВnenuKv[0sef`: ,wH6+ibj*]ǦFonepbn77;2cy{ʥ6G%YYHÉL]H4u))t:NbOzC y 07!hܺ3zDuVJژĆnIz]a=):lNI[e;ǣ;+xQJ?H[_pʃ-l_* MFH~U}rg,MR[ `8a Lx‘8!$ @v.\_R/wT6#cwSz7k(LK}>qfqQp^{xG)g%?Gޗ;]IÎ4_$=ׂL{t )`Y.zЛe/lDjѽunOHj UfBL~USmQ}H9ntK I:o :Tx+V~9@iÊNQ߫78قշٸ&.?bCN |c5?5pBsc3F;|%nz|^&Q*,}ʲa^qG د_26R} D_RͺC rS]\kЮɵ ȶ˻41k z^Ii*j65ef )7=C<ϣӱUu]Nva?H4R=jDeB=D<͈<#iK[VNPq客s8ꃴq:gn/m/ >6XskaOm#iE3= Z >r>hA&mrmd &f9/f]"s$k$+ (9獽#JxsH|v=}tI>93wou=evSzY>i'2M~f]"~)M[[z>oA1> stream xˎ$힯..0szz=у(T]3lc)DdŊ:~  _zYA.y-\酫5z'Ƥ}6>|+>:|=__/R8[S~"|V}ŷZ=o׆o a@^۲JbVIJ*_͏\xf*ƭbWr|Վ#eD>F|3O' ޚpS(&f'Je 9e -+յ6b\b@GXo`2ӱ~gW!cB`H_&#DR ¾#YV9JW9'JB{pGU C͗#ՑŀPvc-O8m@Mn ʑIc=jf뵊NjM;Xz>$QoΑ ^A( aS\vѩCO}+{Vk~b!xBtY zS${IT/eR֐F{{P 0@*r`eCτfU4OXܭhEh}-U7J $iG;Ȇ1ЄgܑtPWʌ,Ө AV `=fgy+U)lҝg)MK~j X-әҟ9֋?bAs KNs(| {t8Xr+ !M9/x]# ;$ p:I}7dvm'''T1 -Ƞ| 5c }xx l IN:a`1I  &P5kn͉0k*LJ\t@NQ>Is1hhi4*60",ʝL R=-ЬВC,C/>^&,{yYH}`~(d?բh4iͪxKޒit.T/4KH$Ȕ, f` T1d4Uǂ_)18P)jz:gU2}]ӽ$M$w$0DpFlC3ހpۮ^ GkhrjkpTJC#R%3y2⢩"I V@n 18kKmF޴ %>Ug0JVg9t%b%Նri훚]d ow uTŪI45=j:{jv$ # }M̳|ᗞ(OonUPF7 =QQG̵aBA:;Il wҝ0{=ڍі*x5Ny&%Py-uQd_~J6#8@ aSp#ǡPڎĉ5.&i J[={nfiZh.:b>S 8}͇Zs=*}C\W$(MVߺ8 y endstream endobj 175 0 obj <> stream x\IWwh 9s>KYHI3s =Uo _X5~u~~ 7>~yGpzX+<|a3&[t*.wק21-B>[^T4#iS<M#YhAE=MfU>앒$\oeyP h@8bo:8HlK د"9/Xm!_Ge#8avCΚ-]̢E tdLUD=`%q>n4im2Ϙ,|H«]Ds۸W'Glo`hV]iC+0IO}םL:u#YQWIBvJGǓ=&VUDDDC10@"u,"a%EV]AUcz&6IcWH܍~1Nj~EoEp8݉|FB6ҨA@Y&67pje%9hD'C-";Hxֱ8vFckv# ""WIxH! B {Q-nlA[툿cpRE\6q Eg\3[.яDۏ/(a7Hҫvh?m2;U'-|TzپCv':YoY ҮӵU,ٓ7H@-j'&B֛s:[́;?ާ'YO26U 1$κO}^%tRi๤0 7GȄE͆);@˄hJ;KJrgGF,R3DtSl"L* 3N{yU~p0LjvϙMiq礙A/lL䫪)HbgLODSH/A"ߣ\m7J6ӵ_ִ"%%Z\%O+:0T;pcX𥘛7$;S:|Kcf( 4G4F4 x'K T>4!\ǹ 1=&ڐ9a*fS/_u;VȕڡG~ͺ)\Gm|a-@Nb$:r`"{mJCց]zp-ۣG$~68-@?9*WfH:5Q45<)i E>*kݵǙ [l$3ky&uZ' hجQ9_ g,q z^ @Q|F޺H-xWg)85j(H)LԈJcrV`FKu7gz!Pьp] ,&D@4&>ӆA`u2ުN0PfNG% h 4h:lgN8XWր^I?ei]T9AG8d>B d%0һO:eɐ%A+,O]ʸYuo8GIqwg!p{=)o8JlލWYFPgF穎;сBݾR6I%V]1$)e EPi #{MϾQz2r~n7 g&2ƒ`*K#/)5_j/u,P|1?b Qa|H^[-<؂4HVK^Da#DI~ޚ=dnP]qGw823\)7b~C !r{فE"?+wQw\_۬% /;W H^r.Ccؘ'5'm{ P1h 6CA p^NW*PLPɑޚ=t]ME E=/#=MdqNr` !jGPj>%;S:2z8O5ʟoo{@O va[b I|Y0>AM^L1LaͶC8=hq*s佫GUV-VڽNOq|9MlP0*&ѣjuNu6MIR*PM#hOaH\UIj6yZv,/].cJȭ$^^HJMw)T/iZְŬjG6ITy24;ґTGKq::;LT5SM{9cz'lp斧pmZS5ȋ 1ώɕ\`SZG]R^,oDGk8bcU^ xwJ]踱Vs+N>Bx #j{yP+J^-mUZ_9֔}A"La2:xxL Uh;7IV$Bά+H!SŁ覾f8gN%a hoB$D1DjHJ,^E$b}O@PY>Uta#4GX޼Q{Y; vIpRķj wNi&:~g;5vB#wDXZJ})=iW v+>EMfވ!e:Qb9qc*?p=hc>8U+j+#?,ۥ(;%>d?/Hk^oxEm- endstream endobj 178 0 obj <> stream xn,힯hE>H6Ȼ9׹dsG EQ*v&xh[;)6OlNnv55~ӏQ, MH47,/+jC:~L<ǿޤN"8*>^oJ8"-F9.~o|S<#d,>Q csʊmlNJ'reE_o۟ ֿmLol7ac:-.a."{Ssku"aV&3^Tbʂ( e06XJ[2yM7("A݄gq2qXp (\VWSU #g@f_gf9 bt$}eY‘tvlJ$gMtB~ib_fe\h^kFzb7˺$܈XFv<9cs k(؝:\T7\ZY);^\ibOt}ݍVp҉g{mA!cw>аR v5]Qmdl uuv=U7!|9ղfkv.P.mzӳD%~I=߻G-qkѺx*"^:j}g>>虣ftyD3gFhvdB(UƸ!gf3?r; ٹWTA s4bPI pXΉVNX.Q#w}r +rAo~1M;jpg4$ݚ /g7a?aV4"$ÀrF2-j~ $M[Z4m>PWE:_&",D]r/}*O1rPmHwg @m/V#C,!1J5;K nںm2~TY ]-ږ/n[utӍ;(UKWxŸAa^ ɓ1qRuH 7sT98!5Pi#X4溓jhXp>OɪJ"v&JLyՃ6 ,,lz$1㛏G6ORWb,+v|@;cJ$ʷH˚PCNnRimJiʽ*$5P)J MLKil5SƷXshd=8+.$i@5BB"^ A*N3ZBw-VWka22\gjs|;m;x %.y[M@ޮٽ邭F? Rau2Ŋ)14mi/sڶăݥF!vku>0]_ܩ͝sL1%, ĪTH[_S>栖)s3a(gڮ4'5Le2躨:b5S>sǑ/8tY6ꖺP䊙GT\(udE'S6ʝ&(wKg/:췄AI)K1GP%ӘtMe\  ;JCkm2*V*b&*eK5U'($ql/qwL^M{]hZݩ -sbr4'yꓩ"͖QnO.FrI-3?ha% Z/GZ}jAqq iNZKW8N>rګIPZ *`i:ja.Y2aULY{Kv8v3=QkG^#agzTFSMj#V F {o&A5:)X)z-K=RRS$t5(_׹ՙњj$FKQ-+MvY\):Õ@']D*[$rԦM}’n,"I+$kfyVn\H/}o@mTC_8iX{{w$,/LKCǛ~I ch!J`[HGgciag}AtV1 ;Sl╭)% &Z R]3>Y^$/sukju^*6anoVA^ExYIie{W*׫'U>%d̉zGzJ䣿$hv/|պݻ~DuaДٰPR{慳*̢Qy.ƨRTg ɖe:=24#rSIAԓgrJNdvk2423<ɭτvٿ? a@=J.@UvFs?'yƛԡխtEB\d:O~xb2ߌvVDmX |"  x endstream endobj 181 0 obj <> stream x[ˎ +" 讹Mу(Y]5=BeQ")>$y} bb__n߿/rlcB&5 /I{5>U*t}^q^5U.Cmn*t0xF wkKÖ GIxeYH%djAVJvUNyynVzu•֍k{`ה8})WFŕ<̧2I3鬳V+an܂Gru"O֢ R[cek _-Ҩ-*A[ g0J(iÌDDSAƑD< iJc2:aoX7ňC5e*݌+_5ShN4ġŞV# T􊡪{z=%<˗5͕1pYt5E^c,IU6Ij&*BJUlkFt$R=Z[ [(QD$>X ٲ6hW ]u)L+`'fQ 5HELd"rޢ긙$DccH2ڞ;EqsAC/́+-ED2A#=k-c"zj=m Q:[f+حylPIy^(lr?hf :0Nc<T/@)eJW,mJBΤZ%CǕM+'y()^%ŌDXTg٭]t6 VFraϐe82"dp Le-G<J1og>b"CW/AjIqwX/%HoW_*e6ebJj0-.I5 E=Ն6I/`GB;y*(,>IkZZLZE}Qh(?`hDj~~ZFnM8|#: #cVX ϶IO';ۊu՘ެ Ap5avd5sjGf!kWt%;g_mɎ 7gv E_fScA1Q2Q`ⰱ4շJL;.VsΆ#FA.H81518s<膌qפ[}D_'T樠M_8Cp.|< `;6#_2Tdns+&^т֫^Ln >p&rUEQ{e@ν5r州A~!^Tbl1`2[܊wpwV tdRTϑD㏛[& |ƀIS9~Y>3,9p7^-b+Q,O]HH%RO<[EbbtVb9kpmV7|/w|= >PWk *LZ~w]=%oTU"UHO՛ Jnɓd!%f,iO\0WwCz;DR&v,şObPW;WrZ f.O{Y=fuhqdߐ*_xتͥGG|ԾM?lj3 ?g&gg{D>嚅0l J/?;Kj9} #tItjKGd =2WY%qg|ӹڏ[$wsTWh{cBόjg䉌k~KQ#wFv(nIs~c6m)9gK,~s^*:gER hA$6Y^v4n_l YU$3}D' bMkÇ4;m:| ZʙKރh`G_Dr> stream xn񞯘 &Pt "%9V@6ᣪXd-YJ03b_~/\EŻu sSc?*VytF,ޘĕ>|?5~?6~'<)F !C||Z'5~∺E+e- wc∊ P7 |/E^s~ _Q".ˏςC&4"{Fc;JgrA1"ܗcG't&B2B$:!(v/ (Od3ײ9켆r )o2v+Z<8Њ)mNZe-I41Y̝vq.2(Qp[(7* M'W^wB #' ,0/O_yΓqc<(ygI1ReqV5U5x^11dҪQ"wkVϓgW #¨BRT@y'#( Cէ+!Jkv +&b񩜌+>HG\Ⱥ*KP/SZ#'4F3M4f4=Q J! =GHx죘x/c0*YJx COvv e"E7F[l)R%~b7Ԭ OzR&ro@DaCFlu wd5RŒs󈯸)OfYYLMd šޏ+P0NrQ䤀ʼ31sTtQpÑT P͹ye_iE-Ŋ%%{rxB+(CѸ406nϞ #ǚgDꄻU5w@+7:G+jHCk',S,h.xJMXOs#{g ױ Nh[rbpnS^3<T0HYMr#UڡW8!s_:*4j@s,kshS-^[PHTtF1?Sgxp:)1b>cg܎S,:pʯVϣ2ksfgt1t"a؊ gLsL3L HQzx+eMD*Y(~UV*A}"]a*VeSQ4,bD49˪ŬZY]GQ9xN? bP" \ 0k ^8#*=Ä#1&4۱P tW,iL%)Dj4#jsHXy)l WV88 (+n$UOGɄ:* yC@'VǀPt-O=]nVpUi)XDX4$[I?NJ_r]T/9͑/\~[s BMYfdS.%7:%+$Էs׸V*M+/L; |NP.\ZoXr<&] FصjDE#p#("v^lȔjס UN'D$4m܉%t'ZnCst(ZjY,Mb8 xNTu_rzK3PZAz]9β*!)8 XLBn|)d<7Z&:ȸǟ|fy-&:~q*HkE0B/2Mdв5)&VQ[D h_b1y~`"md2|BHJbm s%͒((8M e0"pW٨P*>,C=5)^j+WM|j"Dp$YT6+˳|8m G0%ac kGwk5k} kJ&2Voyv3м-PcBdc8X(,yRẦJEh6]G^c G6CНͿ5ao7ߦui<\o_n\K }?O4('7yI~#Ê R w:;QG8tiD [X(Eg[j,E[9wsb$We$w90u_"R5Lw]Hw45`nfDHgxo5,M[yĵ]l߮i08Zi:0}SD) U17s EG*S ]ܫtGeB)U{U:_Ⓘ>4=:L2^NmV]2^aGig/~ep" e9b5}og$cA`*a8| :XAP*YםiSjSyT0Mf LvV=Bv&ϑ!4;CE#)dAR:%$M_eO*'3MzԶXΉƦѮ+jP6ɪ. jrd&g ~A` ;~DPR]S$h<}eZԬPҺh89,9s49 36wF8 R:\'A?ղnHn.A^S@6uˁ" ;:ph' ZB;05;zebD> stream x[ˎ+7WXыzF/ ]}LYGORIv&m%yPMl<'6+7k]~}/ =YU/Z:\–-ƿ]m??l|G1lo'ərcM[ɸ?D[1oGYxvdZ )X̤}Q' 6[ǔ;Sx[$ D:ƳE'y˓:Ԣ8M-@K,s|EΤը2<` Rhj ͎xQl;uYˉY_]O\#G9V8#=xJ@9ds#%|ą@Bץ;,.^WUY⪉pKUHw.NZcjn Mn$fmEU9 $(5gu42Q! -c_䥁0* J w?IBO$(a-iS6@@ bJ%zOq=KTm &k\W4=StH #RɷFktFghm{jTb㲸\ -=)**+b SҼ^Bvu,Zlo7gK2:@֯EEJEJG%qKmi61ugVbU˂V62EtB?Z@%}ez ~N8[m͇׎gĉɏȋ#{p;Xmjzj^RdZM!Ő+FܔlGY\TR8h4$[h1LU**G}4Z4| d`+$ebE Ӻ*"iR:-9p{0"5*|Ǔv` 8‰3Ax <~** o%R̲@15qZ1AM1Zxm>Dz5кs,Sb n!0{Z1:cWŒc3v0ax ge?I|b[l\id|ro>X㲖$zYvaw)[V,WqحBWF}nor j{Ė cfF!yȄIY@ ObgENrwŃ&{棗_F!Txx"yjZ75o܆ 1][I[0,^ƌ7^IRQ+͖WgPt4UZ6wޯZ_xmXSIa5g'.%[EDz^(DRͦQBJ1ë́—8T! wO:~$ @0Xħ V9@d G%FYnSiMkՖYL{?ncGBi tp>}bPJ|fFFqwUmMJ.M;|CUfaDӆ1^ ܏ܨ \u *7N&Szam_<\"ˏZf4_tUL%PCJ :tV1`+|~l8Yo6 )Eevϙg\B$k.ݥD@#lyzA#Z02)栫0*IOsLz~ӀPb09! B`L"Y@]9m(2(iQ &Zʹ([}c+-uҋ t))NLk- :Z;|]F5,0vԑz_eDZbuHnFl )7&h54wLrxɔw䟒X]PjZ\NypaCV WWCCuWqbJw A$:f0 endstream endobj 226 0 obj <> stream xZɎ#7 +h |m9kƹdsڗ*O{Ah[%'|]B-Ж_W5/baXjr]rL|˧?>P*-? ?WKʰ$*~bj/aό/#:{!Xyyp+ Jq'}:5L(:xMmŷpwoqM-?_~[~~~]F-,'NH+/ThϿߗGƅ1j-ݺpN4ˉ1 KKVzUϙ1Ah-a,IK6E1C܀un_v턇1Jk6ov*85αo\͂&jMRd ubz(!JDPB,,DʐLTq%:/Laqp + lg}UD; 2lB){0 g2yu`V|)>n_^w=G:VS[宼ģ`*+;Ri1=(B(!J.Z3Td$ͨ):,VGGF"WPiIi(%{ݥ%GbC%i Z JPyUsO!2FbŻ4P`S VCUUSf!bde}d џK%cQH<6-lũva S 84R %4aKG'3ܪ*)k-s N]Ⱥ0[# 9ms r-8 {yZ-hmyxjŅwf1J!j+k17҉8Y,.#N H,1*2bhU-^p(\ˡK߬F֖OrGsO)ݠ㧵л1t5|\8uScư5 2g2֌Ï扉U00瘊jQr+KaednrچM |@}&G C gqp~wV֑ũ0L%3*ۤ_OUHJBaTZpFmICƤ~}$v>u%NQ8T8 nGIN-T "pRfz`V=M;w8Th gWc Yzg ZeP xx)Y^u0u$& Ja5fc~+Fto| k(a#[o!4J <,g49KV~u6c)()CRVTV~)p.fH̡VJ h@=$K̷`93(:Ifnڃ4;z|HD`Z.HŬeuKs@|̞| {ʛ;n?N@%Y-@7ba=Ѯ#p;b7&{1v z.U 9"tW6/xP>iə׭26M'qjLn/Xh2c NAm 7mz U)_;!)rk˒!Btsc>vyGûjݼ(<>TQ6]NH6!6y1ͅԢҹrx>V O;)Ɔ OǧX{]1#k7}hd +e`{ 6oe%#-^@ʫJG5E5ew0G_pHehCi ='ka1T17nc曹'.B(S1he<+7"3 _b迃#}t˴#vnos ү̺]3~{sGR-S7zD%\"sFa~@L]NjY6ڼ))ԌwT@ohp endstream endobj 229 0 obj <> stream x\ǎ6+ mf0{ؓL R-u4B"YzMcV;_OOӏQbed%QL  ptϫ{2W„{>BOi{wQIk~{4׎;z^hiA'p1Ax"bN=Sk4+O,L&X?ӗSH J:ӄ2;͌iʝ')$%njX49<5!u7IFI?/wm\".ʄJ1H }`\+PƏUTƹ}g譚9FP9C̭AavBAD|NBeDZw}ґctA>M mu" Xy _"""gAԅ P*1@/Xw`>X&#F0 "qְ-r URFhqg1_>v#eU,Wyr$j1T%kf_1 @UJP**vh[DT"Z7D(RN+(إ )6R =ԙ@HF=r<#fl5_RKo(y>qxfW+i+S3M -Q D MgKE79f)XrS LeWzMH *8'0 /zc˨iwMCWBfQەV2@p4&ܡy)^5~]v xMž .7\cQiMD,ZqGQh&y'^Xe\+XfM@+~?:Fw`_H endstream endobj 232 0 obj <> stream x[n$+N$ `6>$!_<9}ǬE]ݭ4T/IF0.-ZYbꁿNmBWbWKE(b-[ ~/zYW_?c^/Lz'sf=o'{d?>QғcR9 = 窌7[ K'e摘]1SӫCYC¯ NW~ %oe5+}$J$3tj[]cT,lbfnBMkNvNL֑tP5ueB!1XT *niD<TGiG)XL GB[,B%tWR[ m+w)S}/KU[`QJ`aܽ+,<Y㲸/-x/Io6߆c*n\]>Uԭa'ݽo?W'}]z"yG{~1i~MK3x},]s`Y2ի>Ԝ<+5D*3I˾Kʥ*Vuu }-GLrTNK'IoR}Yׯiv1yr7d|tVMz= !EÖq(q)|*ܯVr"wg,Iޗv7g:T 4{g:wBnn߻wR Ǭұ7v=WoRw ՝"Y+şs=XEh2u)K;lf=𠖇v^7E)g, xz.jTħ25Tg4uH,ݬvsZ%_r$V1.cRW%h8USOPFنQ0>Rv7j:aD10]]+.5uR&NaI< Ɖd%KC/,QY*;'W[`;ȝ#vtS`OT@VTS KGսB 쯀 < BIT%р#ّHhhh༞.>ƹe<5=Ru^kv ł l0#DXρ,v5@8S;鼟`V<|0|0|0*#QYa>>#ȁ,vy>XCCf| | | | |#diiY| | `sD2곃92_'Q0q2h )Ț#tR|:5;hA."41 sDn H@;& w1fvp#tyGux耇x耇sD4  Ȳ ˞:這Ȩ6Ȩm爾A~<_ |؇=G4 2"Aр 21A&hdh@ Āe HGĂt叚G](H n" }+H'X9pm*sEU4+ 0b \en-^˶W^r=χgTzuUnIXpw^o蔖M\e(j tvfT9X?Ikor:6Wrhl Z,ĵL%+_L, endstream endobj 235 0 obj <> stream xZɎ6 +h_F$roA]N:aNh!eʖ ]DQ"JçA <|Əy'5bx~f\"?~{\ u|L|^'S0q>)H##h-S1>#d_2YlJCHL7iߗi>e*Tfg8E=0q0/LᚮVς:iU(]'*AXBH楊V +ݝg/g[:[bm'YK-+"q,8~X9gbISƱX AMm,@yEDɅrvc54S^~c5:j>mlqF!gmaA/hdжu\4.$ DEQ) .R[/j йYNƽ8qL({wǟQ"2h@&\C>Q $ #g7,]q@ѓZ="#ˠdOߺ-,~%8QMeg#~ʟtt *8_mID PR˥QCYaS0iT0^)՘^[#(\@_Z2'E^P~!ODHb0=_1@(Wjcn'tUm3ax3V>i.̢Zҵ#|EgF }7,\> dtWv),0w;[Ud3=M TOrr!*T^64ByC+ݳd.;P3d/k*JdVeZ%ug; obb+n-`w5ew{3 ZAK47TAӔLXpx07"%tf) Ig7c譡HccvVus]e}x{cZ[A0̕5 `~l6M3x' Tv[L\o❝IM7Y` (t ^fH x~~G6gn_2Մ 09s~jYhEÌOݤcRWa҆rUY$egbF8SQ` $Kss+&q3-9IBD_Cѳu>fm1ϒ,;EyuJ%ĈE+J7׊-0a`i骶R<6-l6߃6v^Ts0]@zߣTK^'GL$Z|J1k.ӧ#t) TZ$2g7e$$A$f4tjaqgl[n!άHGwpAh+nV*#:/3Z|3TޣXpUkeA\==z`ϓUƓńޝnv]SL=lr*lW[1o%x8-PrqLÉeyBD> stream xYKo6 W%,r(-CEskzH&M/ÞKI-٣"02I=ȏiy< ga8}"t@  ow {){#ez? HׇQkMEwxX4듭9a]&k@cbuXhKǐlkV+Kedy4t,349iƱ~{iqrA0ZaQ 4Np5 /#NH  WR\!TgiYU&0|qYy^'_9>͍V+7 'ɄQDZ ]2Au@@@'1ᕟV0FBM /D'^y6SC;;=d'Κa Bjmr-<;ÌahFbA$j}P5eNgt{?`~QݝO9{SEC!(A'5EK548=/M2#<ݳJ 7J!n2%hL^HAs.bH73P]OW ){5 {8ON q+\5%pHi6/4T:z&V `ҽhB,Qo J{R7io(Mؗ8M2#hM[ķL j66z$bn[,A > 7ۜ \h;sH"{ݰDI5dWLc'MCdkOhk&mzka}ݯ1rFriYՋx2򍂚jV;)žƙ`R|*$Psʴ.9|?kqN\Tz/=uJ"=S]$/!UvP7$XKshm UL ɅF.VZd)b5uml Ɋ7wC}WB[YO1QRT6Aod|0VAnhpgu̧sbw'D#P2U+JyO/.Yu̖I؈ù2`"e]/?'Is|uN6ݎs"H{{^y5F~ٯy=%y*ÇR/<āUD=02rZ,:lr@'@(x?7/xnikoB6,kˤݚ86[{A5D\D]lt;fԯg|+7}d6=+S60noD _VVV/ɦ>vzj48 922Z#|fU2:6Eu̖Ikag,vJ H\je\̶ŽWv{8[4ڼ_B'^iPeu)[ 4 C牑ƒ D⒬= .~nި^!sE;f]Da~RhjԜ}#5rfWl2}5(7MjZEZj]m4AjPDntk T7Qӌuºv,:fˤWӌ ~ω6Lz:{k% C[~؟ro!Nu!w,MIQ2p t>xTF mN@g> stream xZK6 WD r(mѹ=d^=(%Iwwv02IZ"{ßX\ ̇ OˏEpxuEhj?Ĺrg\'#UX(|B%6K߬Vb;!)jN')tݕqx|+W:3-Nи2)_2%ݻDP6.WwQfV>Y,=}u0ϕ\]rt\#msQ-cc4oS]j<4D2d M 8pm40f)>*GYc#2aNC xr?Uic!jtDwZt'WQ nT77r 5c2tvDկ(>4k:Z), @6Okh2-@\8GVΰHD_Ua9lj<4BOG~Αul;k<\"wM+M\҂Jmsfi良(<w/x:KC1kb ❧l+vH=2> aȔY@ 5, VzwW v'uG0 ]ISt,/ʃu0rkST qTVc^[C?H'Geo tk[LOyK;G2jQa!H@e@Ry: T $2O_nk I^H<}!(*׾]vAJZԨʍQFA2ߠrQ߅2PCC(û-cweeeL[ǎY1cpb*D\cXT?6HGCƏi!ǰmw+p7˓EiBҎR 8B#kwum^,ovOԳq1!9o%4$4$,4$ihTi\vUʽ 3^2btySfg.`tYSy>ҰVu ʴHwcNN' endstream endobj 244 0 obj <> stream x[I+W}s0` $({IACKW 巅-bb#-__o(qԱG4 :z ¼jR£yc_/\V1|y!"N)#Z çIzzh{n\Fb{!"R3Y(}ߙ`ԗ7Pw9ۿߊ[pV-/#l!EjF0/O&Xⴖ^3L΀(-˪qeaaj"9FR-]T&KyNbOG0K/ıǑb34" Y_%J*Q5`ΠUBk.>@0QjI.؉}IbGzGy;@e+reT{-@&[ɬl<)x[vi,3 wvFߵfl﩯V\Oi4銗Ն3lt(|g 30$x-@\  ,Xh: v`` X,0Xh4AG&=|,XDZDƿ {T7BϼlC PjaiXmjX5VS VC +]@Ӫ V7~~F|䟿i=n,]]"566n(Xquq2ʺ }堿iFCpDn^Spup)8~QV(Xd4sp1#S( -&O "NIPOk3Jr:^My"bH"?51:pbM^tEK^>6:mᢎh>EH`Ydj f/0ET4D}.ӊF~&j>ɋ%A u.dJ!5n#K8HnM#Nh_yt~Q ㊌în1Ι ̈"brXf~T.`D $L'5= nQ|w8K}K‹-Gh՞۾n5C.}!5XIGazOk͑?IDsΥMsl!袆P9zV>((5@A(os dƮ@ZŌ~;a884ُD-~Wp`0{G虯=)_EH`DCS;EԐU!O8 }0 e >_a f"oƙ/ɧޒdMy=&I(sc g-^w]Q4gMuP-#ڧaM\SڣN75xKBbh077gUDJ28ۖ > D^rT=N;69q&Ӌ[mD[b$o;'wӏH7D{}HJʛ=B)T|% ̻oJaCj]"[lgX'֚OM(zwmi{&M癗Q2]8E`|2J>_:3{Rمjƺ;'/J#) |jmq+H]Ҋuaj>uHnS"S\.;,}Kb:I rvhV] 1Gv,e)bXQr[庺k%2sVR%?,GOj**wIXAۭk8jх:jڭ1"$5Un6eb BH#Wki͵P$^^^B(E'kjB9{q?TJh|\yOn^Vz2 ~ۈLmϡN?j.v0C\խ]Q#Tmx|fV4QZYs,n#Rs%8qg;,ug-7< ,2pD{0='O@]q"2ZHF?{^!]fjfgpCbs14? xE`(0@$aܝݙ3Q'N *wDï[gA"P)R$8ڇ8ѹU67"'gS(9>[5JB+4[#LﺣNY5PB})Gu37(4Hzf<$*KH)ʬ{!wDq]r4*/=z(ܞt{۫b'nOݞu{'DrœzNN1R0Ub> stream xZɎ$7+RZB 0mCe'PE2F#;*D)iE?xxEl7~<-˟Iyu\bYJ( /]Gp}2"ʨY_NZ ~y)tx6*3>1آb -hċ r t z> 5}ϜPjgtRǔm2}Yv3hY~Y)SߏM3gr [rҪc\f#~2 ֈKB5"Uh R*LfEC`E]bЬ(TUE 0*yfN率HcYy@* C)KJT?w:W~rQF)>ɓFXP^g+柡``bq@7$)fK}lzelU "Ĺ4X߶?u+a- cuѓy<)HVfD +qԖ}Wl #[;ynyl=4D|ysj 7ǧAkooa=^dT4&;_$RH?ez2nV+;5~/TV99GxMM;;;Y|voP*|$wrQd>N#f)t$`8BX5͋>)S).`LFR' r&HQ$Y""Pw?TW9't4K{dqlXR,1Mգx2ţZ K?~ 5mqcSy4Vtܮ0xq4S-m"pz@n%:ʑWu:t Ť-;T u^eV[^Do%ޫO+Jyw p-w3{4p|7ÖԐ'vJ{CsХ/ev}&1Cܺ12oo;2#)\Y %n}Yp;,|E¨]d)cj`%QTuG`FR8,oi2LsR75R)HRM8 20{JKK4F,]tz6ݨf eI^/͚ עD3fJU￴A:6x4oe^ fZ|_"%a!֍vԁ zo}d;c+yEo'`#:cYڭNtGbVߋYGauY7(OFSwuf v[]*ލr)N*&2g[Z+^M-% kո\,Aͮ< Wo/w3ݥ=X9E\ˉdԥ6tV޲1Y7ro+uWGxNv+ƺ,x<;"9L)s͖ΐowOym Vטxe۞DR،g3ۏus{8 fIXs՘6̹Z9O. ~m.cvX}$arx̆%1(Nᓯ[f,̚%52_21>Tqmw,}ͭ|>,*6CO, endstream endobj 250 0 obj <> stream x\IoW$rķ ?5K0REEQOzLgE,<ĂO˟YA,LXY?9Wņ:>&>/ORRkė'T,s##R[ #ymICyZQtHcsNX ,#d߀2УN4:*7Y[_/.Lo.O^~YLP+MADku0L_OB0H3+?S(aAHbi*ayq= !7g^Z:-cXܓ,%Ò 7u8ZO_ƓE';<(N(όȧ#)53)ZjJ%id=㊁3(*b p071+FQ((x(C⠹#gSCYO9 ]4NM Yxye Z.8.S+ZXE7hH%A(il4hg2J!jM  q5 ̺'*Ne.5h{`wYauzKx^k,P5/Ϲ0@%&՛`R1 &0`b &UZդR? &Y0)`bi5kOىtP> =-GRuGш,('0zGu˜M3GC2zDسC52% ZwPeue+s21[r&||q:̎yk;hF!LwiKzn{Qj33=ed~+4k5S!uP|2wZj*=قƿs\ [: Aav0oŕ-7\;!I=wVNψ7+P\#6گ7,]oܿ?пӿ}c;sæQWQaJ(s^b;MoږE&N&ϡEZmd[R)gܫ{7Pv jdhWcB=C %?Έ|@X,w7yGɑX[Z*V|* P{uw]Tvg;_*;Gjfʈ(SjC7z-i(ٻן}#aKjMqТ|&+-ƒR^)phOIarHqnH/p"B2ϯ)AD)IWWurXRTve>5ݺ["z7H+ +c&oOB!F7͌d41i$ܲD <Ij$ʜ5LU wn3l$% zgf*Vam6H##QM>HO##$Hd ~GO9lmH8+Mۻ}twIǜh%~ҰDKWS鎠ȧ;(x9෩?m endstream endobj 253 0 obj <> stream x[K6 WDՋz z[tnEaORlf IhRȏE;ׁ ؠ%$_?= ?"F Op$8(,//s>qL|B +JҎ7}FnF]]w]|4Ρ2Iqd 4xZG?sItEI%RA}7 x]W0zsaid]KҺTy*f7 0X_!&ObC zpx?8Ə8#8Vav h2F[i(SYd"rt-DJUBDQ_+PnKBRQa A桕_=\Gc}#\*YL7 |]2:4=qf WjCƖ ,d e E81A\!A&;uw&m mn5ܖUv+eӎ-U.εd=&7]n7Xu:TYo Wv!E^g|Y\? u`v$#m:t ]ϔ|7 fLtij-ܔ9ߍr|YfsHNNSu!:)s;S c RK)n]p ˤ[nzltl2,,^#kd;o2*mw#Gg0fOuZ0h;apPH$7EGp+b'+kOu=QY[Q,OLA[E]@",@t=*M=HfMd B'iOjӃ wmzlӣ$r2[kzjӣ4=h6A+O)/DܝZε/4TzƠA~)=fz8F -]FniT+๹Qq$F#wNw.mC$RoS9("q" ,kE_\+#蹠z}LS$QR364}BUfZk ŖzptcjLDFDfUfZm8L"GK3QAuL4Ő|Zĉ a ($*AŝK7fLvE5"\W\ƨ]nX*f|gG/G]x4Sm* dxᥥxT+n%VJѩ7Hok2ڍi\bOsՂIZ\csPm=\1/A:~*? ;? endstream endobj 256 0 obj <> stream x[Ɏ6+f/I[s&,/ml.bڸx>dPtP m->w? ? oA*DG_0fj+}sna}vC+%>;o71^b,mwgvQPFR+Kھt%[&ٕ}-oqO4)i̩5S9+8uuϷ߆ߒX-t@@ZYm.ܡE؞ M"^4t"Y#!"-)s^Bsl_hV"mFq1Xғǩ ^7I* Èd$i)ݴSe(80_LN#$xP(ho~}YI=8T:} ;I())}h̦@@ TӹmgC{%]﷪tÕO'¹h,1jyư2PDE [7X̱d@~\B*ki+{̓Ewu'`>Z)|nvV'f'/JqrҺZ.EeUksS 5Av 1)RʘN[O')"D`yaccɳ.<>.,Qivw[Ftn7K-ҥ6-n-]9$r-_@}rtՖ/nO\@.1F`\qo]2ƚPDt7ej/S%Jډ,Y@6Vڽ+=cdc'nPsaу;oO>ؘߟ>y1Qboh^Y p$< wI> #ql^ֹ קv^18T⫠R^978.&Q @j԰QT!yD!Wsyg9( -%4l ӟY|?Bnj} endstream endobj 259 0 obj <> stream x[K$5 +tyI> 7 8qUtU7;h5*L:dp59\†cjyx͸=se'>W|$! I)Kα]՟u > kGTs=d E "߆L,2Jra,=ߞ~Z* {a;P%ډfN/w%;捁w(( )^lR[TKB2טJxڝKvB1=*ӐRP!Nm2SǞ)2oy1rR5" $wpI˜EUYQ&b.tӂ)B'"9Mҷ"\Xl7⸺n0s'״7+1x"~ǟ# r'=?->Z1è]M Z~<'f"/VN *,{9ҋn+}ʩZdVێ展ױGF#Nɛr I{C42"Y2^h-^ZH4HiS@.=9t(_ҞW?q\86ZD?IJDreAQ-0qmnD&Xy1ʩCՌi;OwvT-ꅦ4=Q>RXKk) mB_^ ̘A 8@4q{-&x歀i 욌7mC+{V:ym2wnؒʿv#Ҕq\VzөWSg!J~{ްioG M v)[v|6I!o%̂n+iZt|L1ˤeEw@v`ce𲡺{.Ґ`R0}!Dr&~4ajѼSly^jf2o`'1;=&0̀D[j4*ӖyakӀ"rbFi9wԀ#ySIkGh7IMS쉌,($gm ^}`*`L:RWG.| Ne ʟkb#N9ԘrMJQ>˚\0,pR8y)֒%^hW/Ggn-Bw;,R"%TYҜsk%1iga3J᪼] -ǂ r5{@dX,ݎ]*$rrGכk v"o=.~UYn<͉75Mcch'QoPV鰿&>Μz9U($C!ꙕAs_]4 4ȯApMLk{_53\ .5uni]_{p &(wĴx{또c3$`l; Qv8c"a,1@=;f-tXnH W;hicFtVkF [Ϥ- m2H~$Ɯ\. _MR\/;"#EKLK#, f%mT 2='~u?xw=R"Ѝ|,$Sf2O+{+ Q,ӳg,Oeq#W+erUN8f5>ZJN KUD{ T1ɾ"T~(گeAwIm 6`Υ TuWXA+:9L3~ùmWݰڪ۵5:XAl;]mchڡz¬|;+Ǣ Ǻf>0L@2 :ÿ4XS F7V0ts4ܨZ܃ǘoq,kA@HS&"EΔZ}2 ϻ-)mON"ߖ~nMz7 endstream endobj 263 0 obj <> stream xڽYɎ6 +h_B$6I߂SdK~?EI*w{0\%|ȞMj𧦠i'ڽ4I&5=&MaRVFO/4ܭu+^NQp\NƘ<쳔޸P.;Xdi' , oyw k\G`qŗ weH;+)$x{r }-A;M{5=Nߐϧ_&aRtӿIn;}lHB5SH|^oREUQ5(< ZLդ3Anyi0Ѭ#@wpu;(`rW`AsD>it2RJ&۹\Fegn4Y@Sც Z'mԄ3h^?TjoLEQZ}iN,ǁ:%kUS}F}$}G5UCIѠQy+ \4= K*IeJf{lNIXk1ՋãJqf7)[G!yM۱8vm3h)gL&Y۴wUMגx14>UojOᤵDp @b)g~?6%}V;\i S#.>4u⨿s؞'*Um#+zmC~4jB,pT,d^aB1&RPE}ȰB3w+eSIW,\3#f5сf.l1+0xV/ʪyh= $٦D1sq R,y BM@?sٗ5#kc0$[(/z ̘{Xs|Xs2W>.2Ss,1?DTHđyszժ"Շ$&'&PIC kKWTJΥx0w|K#vU\ 81d LF0@e S j`9`_2YD3t7x1yp-$7[fڭky.] K[!SʱoA(Y %DHRcl`1GXz}Ė[`eh=aeMHl, vE9U*gEnewqo.Y`^wA%#t70zt9 ߘ[m(r3L.K]JhP-Yk 4_c> stream xɎ힯#Z,чMҷ Ws\BJ,Ua2EwE."'gk)~?EUchXqHxX>>&tǏJ a~Qڇ7ƅ[maĈ0Hިllqzc/al~aU viDKQ0 iKeV`uR.}[= N[[* 8Id[Z=,(Г||&@Drx#%ޅ3U"Sۀ3-Rpډy(Rd#mgd9M&6"kekjY.ۖ𣽸w#XԵZH/ D:6VG 9 |_VY4MlAH뢣ck/LAI0U&8VǐDTr5:gEr3iI-Y4t m.qd.)(z'dH:~ &y"vqO O XŰIQ߮7&QG?K%Eu/ҭ, V"Ȫ&5g\ySH-3$d92Lki#B}]8" xeґ[go mBkMi+7[u q+ Kl-["NDBcSۿI(4mF 7E[խg~ĭ3 5oy"vr-7(|4$8%с%ڭ2DgEzmyM1CPzR)[_fM2 H,/ pqhIo^H!X&qLG HbIc4Ræ35fyS `~߼;5We)UI껀U}5x 7;AyZ8FA~6RF3pdGQ^s6-UU {qg)Al57lCt&,>_ ȧBf;;հSʼW2΄83j| 3 '|ܮK Keٹq_lHx%*sOg2az G( )&OGF) 4O]j(=I (JU)72n^br4)RP =.w?*sҴJtApN }kMX;csjŪtgiԗT\_jgj#gK<0_`E?1kעddCn~d.g)S/a&S(x :;*butD7 \%I灈53<3 wZضt VKm?cPNNS`7( ,pNF#G BXJv.Dq/TxR+ ;Uκ$OuI uIv|!1{fzY"N5G\temI,5fAwSIɫSRpy<䬜 %Usvpe=_8iJi`뚁|c=7%u~oмA:ʫK ~Rtj97dqi>JՕia)OyK _@\'#`ҝCxoIح1p0z 7+M;8 eRhh+#^*~hWclMy2z\bOv&Gy#JC )[4Q܃!,N [42IzT&!摙k8kD'SN buҌkԀӍQix]+m:+r4m]F{L瞽K<^Esy}-w[ػ׮<ުMi6^WtjlV\TЪry4ۚ6mKoxfɉZi{:?7yvaIp41݅ xb9:mީyu^5 ';]ܪ 0:>h7۸.]S㍨Y&Jl+ƄtvK?7M}َ{m.']NSw*zvbe[Ɏm)Lm35xa VK3UItzMo =Ԫ6H躻%2i(oB$߭13(;' O?KC\ٽ5'ț-fx6[my1/Q5UNpdkcܕk~cry:~[m8 ^S75&iڷ2rj*73鸴tSLf5ٷJNjU7UD9.WRb_nEsYj7Ǿ}gSv?t zMq ۯJw ?C|y]΍ )۔@ endstream endobj 269 0 obj <> stream xڝYɎ#7 +JBmC$@n-vsߏƠ.EO#Y~,fY]b* ^e7fy/ƕ6-TIk!幗'W u$|^ϫsX'hmޗ9^w_nnHB_ dPӷ/,O?rjr Do..>#H%CV( !uW"PL R6ujIv> W8^wn5I RI祫šF͆$BcH e Tn* K+WpM .h njJ  /jYj:'"'{8+&JMג I[0m.:#R5yseq}@3ۘ;ErEMgCCTHb)#9|8U4}!AYIV-*~{8v^2ӣy]6cnghsj;u<1`1Ny.; "H?Zg{͎j !Dxth^E;$Myn{\61&KD;+B{HŁi38Ȳ܁l1ds}[f[hf߲̻'tHܟ:KaVD_N K3#*3ڏsнIW<1"I01 'cEo!lɢ}Կ0ѿ9%1.d}yIhW=fG^Od7o1:r3_k+\Y֗۸(:Mfˋ#ֳ$z's#:m5߆Cmӂl'!?FϜo(\/?qYc9ҪbY/h2^{oÙod7wXJwUk|G~FSx endstream endobj 272 0 obj <> stream xڽXɎ#7 +H0  I| rz.JmBOD&P]!wDnQJΈULCC*8uPJ_6#5,6BP RB2iZj4)+yJQl1<42"L46Q}m+ 2$O<,pqUAȍeayePPɨd'+ߓ[P2".= -&̟Aba@zŏ/*>/iZ5uozbDzZ<[zzI ,ȒGRgAž%9][8*Y3]74^w$ H+eZe5+ZeOu6c4\"S)s𻾣|5m4k6tDq.GTdcnzo0nQ هٽ&ϔK[o^Fy?B_Pݲ<D}zUZ5Ny +y\<N]}Q"tT}wX^թn$q .j;e~c~ƣԪn V17۵7]QN &\ΰ:78g9O RL\34Vh&7oe1fy=y:P-=#^c}S)-KNYs^2 FcU|9B]vۗr? 0 endstream endobj 11 0 obj <> stream x\k7>hߏ@lc2Nvk -wk[jH_簤*Jvcj=nEV>yxI*%;))e;e:cqq S.F.ԩ%Q/cBJi] :ݡJyއ" Ȁ߄.ģ۠> V Hyvt ^uϧ;pddh]N-wQzHE!M&e9(e&)<"mVu8LǢLsJ<B; ^V@х;ґ[GQ(DQhOh P U\VL UJv ʆ9p~ERHTE #D"QD(|@5|DxH,J%ńNBR"[%99`b%ѳ㨧%LzQ*O[#KiI0Je<*y x'Ig/%'.%=ػ˰Б]qÎ#?L RDBM OX +@L\X`H]8~9|>ˡl )H[9&%QH֡?gOw܃F M hG)W%Eӂ^qlSai:p\Ӿ>6BedBU/ia:$u 5Lh́QKM`(? /菸/%Qz@ ή%Ѱgj3ZȪ@lE\"wCF̈- k^59zpD #\ӇiP@'?,D)ۓpJ{Җ=lYEٲK+RW#z$fFR25-h< .FeD&Ҟ~ԥu$Ǐ!E}@ U%`vF ZQ{;-Q0&I e*>m]V^pc (PiNAT fCV6M"cP"MB'^\S䡅qMdOAV2/ZD=.fK) gbJA /6DOªS iؕȊx+(B_-QE/C7~\.^ͷ=/nfϓESB%BĜ !MƊq8TkBĐm/e' 2mǽUD.xހ ƶ#^U,RD]SHЯ G @&R^VBR:`lLB7_{umFU(Vs_soKB81s',8sZGwX˶ၪ@#0V$PPDn #0Ӯ1 er1U[o{sϙ¹K- ǯ%cNlRa[!Ɯʜ ;$ڂI[Ω)ީ i 45VP>3 0fk%zdbq!#TlB%y:'Bjcc7>\Φ:/g"Vl X?22O!71mvOi.;_ߣvo}l7ba{u>]\͗ݼ]mn34؞z!<~8. qY&@0pT"l9Wsptu׳|MvEn;ХCH$s&Xc訿+LǘX`cnV=_5S!#fX/,}}_϶ͶD Sr&Ӧqjys: ڂ|actv|qy+zb˹V]/.Y^^;ٿoewuz5[C'T|=zWy7_~osDV׫s ww0@X'\ ],֛-Yl쿟J/w۫k|g@=L*xXDn!?we2mڱzCk}|2OP.Y_+]o_^-{gˋ5Ice[r i;kt/ ]JU6^ Ռ.o:_:lwAB#:ARpÎvW:CJP ecw@˟rd'7|F Nl>[Hls_9M$Wb쮚/FMS%/&Qv;ȕ i)mg\)Ds$/UF_ O!(x(ܧ;cb{yk__Ĩ/>~ Di#o0 3pi!N5Rjr^ݓX0Sn2M/r3u=e&8)SnTDUKc8U֞J2t[#YF K8z)R1z[T)\#Ya:LdI\#Y ɥ5B)DK!ENƵ'(挐UP~gDa>U>HQ t=Q ~$+-i21UOGeO6RXC3M;zª ҀR֍MtL-{Tya#YǪɥ\` J :(5L.ZQjb4?29NJ J8!N6mR 1NL(թթF 6ӤmCN6"*Tutkx=+FDmD,ʵ[ qg09!=UHKh'b°o=ŊG>UHK0!2qgk+ݿ?D!sOW77e*N2z~f!@' {zq\M 6jOٗ$*|Yl7=[]۳Ghoz %cy4\]0czD rJgW1_L'96*.!~*?lk_!V*=~۱e[hѩ00gNtq]p]mpYm?!3]3~8f3\ۼf ϟ˿)[#q;# i -5̨BZΌ*5ץЎ*!` u|LsRLV5[{v|n;7b=g̐~qa<3$_-I(W%cIÛ͐q3fTՐjru54ݓ&?eL|ݥOyRc;[=_J>:1jol3vcMYv-+S hs8`arkl|p63dFSeƌ+EWLt2<?tHO>ƥR/%  /%{>Ȟ ;⏘K}i¨/% Ri(% RBi(% .9\SĚ'$gNֱj8Z BWBWBWdMgGq)-KPj,Pj<" b,%@adp\ h342RHXTJ c*%p䧔tMzYgwĦ?P84Pu)E:bzJ{OFޠSRч-RxnUF:û[_a|uZ`Nv5Qy-8ؾMs aߖZ5g}cHxЎ(dS8h>ﴻOY_3Ս endstream endobj 462 0 obj <> stream x]ۊ0}\.P/zHIo&c{ ?f ˺Ix70N*aawˁ\*U@c"$go3厙=끄:V0{͢7kvKWD@!g1ת$BTa탼VJen zP#<(ȵ0+Y4d({Q0䎢+T"}{H˙*$b9 1ocIJ([L$%VI: ^Xx1MQDg<9-N{r# ^EME endstream endobj 463 0 obj <> stream x]j0{1&Zۂj+]l> stream x]Mk@=GڀiB>fӅ.ם9tagwqF?/6V󏶓% Qww+]઴CV+9LO NhkZ=Vc9/qSrWՖ/X N\lG?@[ci1F~6[^\`kJ_윗)ܠ=2,ǩK! }/ Ɠt;]{]-K|L#C E+0Bw)"]L2ʌDQHoKu> stream x]A0:n)Kl˒6 Yg)M4{6QC}mjHhf4^TwZ }sQ:Ј:ʹIkFRo.,}=/2e~~~Kη: Dgԣ3݂EcU2) z9w9ipv8#AϠzjTNw$HsO3Yxq$Y:3HX \ϡG̃47q8Lv^>#C?YX R endstream endobj 467 0 obj <> stream xڕV pSUiJ<@MU:X*C->M4mg6ϻiҦͣI[ڦZDV*+PuD\RWqvuv'3g&7wLxk׭ݸ32=4?-yR 6c$7'g'3%i.EaDבnr\k5K6ryjGDhazU2{,YKī*%8@Q&,P/UEJ|ϲ2z+ʅ5 ] V+ْNR,^[%U3 *%+,rUH〉b\:y+Hx*3SԣjZqjʠ2MTMmPOR[)aţ/+ikҷ| m3Rf & =23m˳6dvq<֒^c1ޗc|{2H~߹ிl UK-:ZnB^sM Pu34vzcw98x\*҂k/%6N|ybߴ.n'ѭ;fw!-\^ hW9~pmD >ۉcmσu* 2V+ hn:q9 o8 7qa h-Xf&.Pew=^VhRUݒ(TT/D'^xA@'ˌE7#~0Ó ﺴ@hw9:c c]] =!:n"n߀3MhqZCm7$³'&t!'3\~"[8 ޹‹ȿ^^ WNvͪZB]:;=z$#, <^Wywܢ4V}-^]s r[i24u5jZ֡FZCGQuWx=}1Խ(-i8X$P M;ZMddO*0#MA BrGaOr\Awh Cǎ&Tp{Qj{ȅfjnT2v @d,gYD_t)>p)YWu*2%riUjC(oƪx Lʕ8g)BiXc߉}%wӰ Mh#l:ui.*2pI=]}Sƭ몖{zˑ<o܃t1EdS|O(GF^6Ǫj2Q(1Dqn>s ci6 WflQ/(A DoEs94eIksV\ &SCmĊl# tEdMj/!Vaawʬ)5vBDqcMn#Vw'5oOӗ7V-jh{e; ]ypxwܞ6m=uxζ]bD΀;B4Ei5:XaGuQvuߏ.zVÑޔYóvs endstream endobj 468 0 obj <> stream x]Pj0+qK)XD( uǘ"${qz,ut9tu<[MΓDZѽ<'b8y7M$:]62_Q{HIQD;FFd@$O.jyUtndbي_h5YI36ep7lPiWi xt endstream endobj 470 0 obj <> stream xMMLpT+(1(F$QL< Pc+߱۰CM8<Go$r4S;&b%oJ4ׯ\z ..%aJR [oVm/afDP+Br%y&(HE2LP+a01W*ƓxЈ_ʗ&c7"y& Af9U[0Lj!γ8c FPD~kF+&eim-dAuUDJa` #Y  * @@߼)) ("] tr흇q}~h))D v? C4 z(B@{=yOfXx&TpzX7SVf/_?pMA'8`lCzn:.FgWWSʍBeD$Ksӓ/Q> fHLƦn7T&Ń)Q'ͻrҌhu69.l`ڇJ4ȅS̑_Kzg_Qxl,ƔU#0>'02yg Ya00|ۓLi4UFʷ{\NM奒j<q}?])- endstream endobj 471 0 obj <> stream x]Pj sRJB!%P-5УI*4*]MC#3{ckM38%0`8%(Gc e_5IO,۵kY|54[=(9AU8ǰU#h Ǝp"o/Nh#,G7OiTTeɡjNlcaG2F'=})3oG$U-!ra(o endstream endobj 473 0 obj <> stream xcd`aa`dds q v 44 l2 ?d1g!"Ћ?,AD~j@q+##`}ĢԴc=#ʢdMCKKs#KԢ<Ē 'G!8?93RA&J_\/1X/(NSG<$C!(8,5E-?D/17U =土[PZZZt бY4'9{f{?3T^%:gnU6UUv#/._ @Es!*Vںl;.L>1YD37kLC{{gwKw˄Ω.W1cݽMϕ[xOlqýk3<<@T endstream endobj 474 0 obj <> stream x]Qn0[^EW!BqI錽`,?)]>UQqSϼQ ˼i0JF F SlB[>:O׶ vWWE/+NgHS&."lC ԣti6~pB%YB.qLHRJ3H2#(ſgt=fѫaRj I\x\xNb9cO(Wӿنf$^,;(jV6˝_] endstream endobj 476 0 obj <> stream xMSmLSW>[nL)wۛm-l*~!Ȝ26 FeTZJ٘L|L-ЂN's(Y61f"~`GX-10MI><EQ365cQRJZ5uNVz8D_?gMN E*U\JTPXj2B6RP/bUx!Ѩ3|!EcT Z\*Dԛͅ/Z1cQL)gud`5BHg*e ‡N3IBYgR u|I+dK*IBl(qhJ! P*B)_7t6/;sNJb4N(SN4@ %e<"]Z[A)Z`aqy\mZ܁q0R5m<Ra힝1V X/k 0;-%9 ۇ\`` Q]0\e:$FX -*͸Xi:^Y' 7kf>eC'wJ.vFycckssj^Txb;d`g"VyUs1!?qql6u(P ֟{/;vfyVlYB20]bXń(g&XVQ,-,^ЊҏeK)g7_$F.-z+!5a:1 xzV¾d3 SMyMQuT~Vۿ&,3ڛIR5M+Unb{ EeY1ƞpxc_s7%q<<ڞ1}{蓬,'VQy~[̔l?(G|<9nws`8zqci8w>oJia{^ud顬oP2pdR1I}>>n*b +|ɰk5ŁCa[GSwf eo1u[Yz o317&e|̋ߨM܋ؔe,IR뙌P8CC,z!m=pQ 8 Ĥ&ŐGΠ|l3h+_4s endstream endobj 477 0 obj <> stream x]Pj0+渥m Aj e]1& $D7y3yxIQV3$_Έg蕖'suAif .b$Ecۼ_Sp>U$+Xl]Z#+N[`wû0tE'_Q@IGt$r 4VU9A-=]/~#fo9aOqKľx} ڛJ%qC\>ch1`Vij [#w endstream endobj 479 0 obj <> stream xuoLuh'SW;1L :|A bjLD`B {-??z?ttWPFd[4{14&#{o  re^%j|I>AAQTjl>h|턾4uKxbYSfCUQ / >'E1W?/uPDe{qfGW$&b(hw)/Qd({cm1Y56GKUՄ-f2wH8e=`{)0:APe#:bDP9T#5H\!(DchhBqHdB[›E,I:$9\\]ԩw~t #b&ȍǀ6JpDG9.&XHcLtX`!p0fA>ZѱaiC{W.~%J␉Fq xdtp280@xa#0X-M/\>(?NA&6H܅ͩBiL'R٠MOBH~[?U8 ~=v0޿we[')XVFL=!O}QdRYUGF z&-\Y`oa d!ʆpTe !V&.MB$;ɶl^4F%pUUy?L@(¯4/照D޺~K!d)Ifsٜd^\Pb> `{Yrh `C `Ѝk59#azρ {grc{M'|Xsޒ80Ie71X+"=f.:)+eug/wk<'niQo<p24=cw;o"m8)Mm-ǁec3sl~X*=nb>LˋdrJŒ)DYQ=UK%쟋TS_ endstream endobj 480 0 obj <> stream x]Ok@~=oM V4ԤwTHVY!߾oȡ ݙ7Y7-BpKŹՍĉ.v<_4m=2}zMUn$wom;O.rVfq< |x$|"+HB;^;BSZ;!^6Mwy4dZ}/Ǵ;t#= $pkh諚L/Χ8is[9Kp)KK[ }PH ;ΘJR!/b "(F$Br1AE vy)}Xr4t0B" |(3F?4#tPA3fB'|SPV{C!Fbvhx:9ݘi۰=Ob|(b endstream endobj 481 0 obj <> stream x]Pj0 +t#A @ic+a]=IO[1KgmHEAir\#;8v^?ޮzӃqu} fP\/;y^W7~qA$MUU:! 3#˲Fe8ɛIiE7Q=(.orEU?iAm endstream endobj 483 0 obj <> stream xcd`aa`ddsruv  a94L?=b$^D/@`b`ad(400300r/,L(QHT04Q020TpM-LNSM,HM,rr3SK*4l2JJ s4u3K2RSRSJsSn%E )Ey@G1]ǰEG+1>{y wWVU]V:{<_ ~Lcb19{6msxxC_d! endstream endobj 484 0 obj <> stream x]Mn0>H$H"Jrb)R1!ܾ͢ كWZ Nf-,40Ow#_6(\bYg-N3j:эԴjz~9Ku^ǼX~y8Ἐ } fP7rZw`p ($̺`:u~`oڋΰ> stream xڽ[[~ϯ[l%a>4#u}xή+wx85fsጆWZQ Q(%e+Zq$eR*"#zgI %e&QyI~1)Qbczk˚gMRc*eS1wU\V'v*xZ"Qx'l`?1 }wFQH$1`P[2ز& |fĪ9P59h$AW@hh ("dI 643 dV5 Jfـ6!ʮtƉby ladA̺#TN_0KN%v0E7@kҳ5Gg!'M*g,,)d=ੜsl 8ap>!1DDz%|YgcxD<3%B96;gOI ˆ{EFr\Iܙ)29 %uo21ּvÏ!X7/D{Xlgf-Ӳq~DLv{}YhM߆m mfR&N'(NP(?t*~[pIѬRҀoϡnRb## f㷴Hݷ8~yJ{Vx)=t< Cݐr3>M gfkiG|#!Oߎtq6f6| ,i6}uQ6i46?2C#YwRl|7~t۱>͐bo,bɏȋw@N2IAsMaǸ4F?M\dh[6lu8؇eL#6b=^Q]U+$)xX~/C1˗iMl[ Krӌܯ7Ni^ 0|rmtT"psxKؾ"=|f/WnkU%^NW7۝ſ|Y(g;k}WHXq 50v6$r#\cNmiȦWW ;!wn G>M@o6#pjpǂX[הذ0Yٗav0aam*'o#w1F2ϴwYf+[iFWGk[֯A_f875Y}Pf_iƟfWR(QCVŶ՛'[ƭbc#^w>^8Nʛ7JZ2,fm^kׂģ߹ʐEA%$*FIH) &%(F_xD&@9/~pAY7}~`|stq4v̹\jQV$"\U n]9C*B+'(NPd߫xA*rك*/(rTr"A%ENPA "טT((K (rIEA"7U((rQS%AI"W2U$(rr⮔V+ʼnE`PYo{-,g=Ye7#mJSíp$W['u3M)ң "EjDҺƴAԦ+uHm&Rfjk PţU &לdf?HB#ѐf5PUyFvF4&n=1{#{G"#R5^'ɝ3a5_ǜzIVR3w&1zH:ofj@)U?ae >NQFȟ@ԙ˭4>vLjAȫҺ=0A]DT#Ș ױ3:y=)u>n%1rcZiUVBSKSkSSes%[dxR!Lr4U׵x zs]Ĩ.TlK6%t-XRVTKz5=բjUOZX؏xcq?VROMBqIHIBmH 7&wZK0!SN;y5|" Gk֚V>Ղ}drʲ;3:uSS:i5B\GZUܸ_t?Yq[`;q5BXGCԄTeyQXn-V-v+U@úg48Li6nmvI!'89)b 1eL쳻SWڞ}sϞ9R/7ۻ'__sE7O^]}x귛W׿~T?>o??>}*on_]n7O^MڴI/LrEQ꛻?6}ؾ^y(puC6Ό6//~kelǼr)W?~i+D~ *_QR_C(Rjy&F4d pʡ6?hKxMԣ})~/<&~ďLySS'HF:?aMsg03 J])EfP_J%ȏeAHXz:hG[2ゃ=ӕH܆21~<# ݪ> stream xڭX xSe>!Pќ*XqCQgD]Bi6i;'&ݛ.ie@)3"WpΝSƋwy?ѷ/M[0w%ϝ/p>BXq:O }%ޚ!+9__×GJKR6<=1%e͙$ɏo /XH,"K2Mb|G%@{>v w}O7_ 'wdZBROw 3xY_vI?b͉O'*xl%ܞ=+.ϯ alѫp>";0 HJ)Pyk9b^x%9Ʌ Jʕ }/!>;*lɩZ9ZX\S Ɵs*T|!!.]4wlԹ .. m*͉l iqb{oT+xw߽ Nd@U`2*RPc=6 ^o֩rtQor. Tj4Jց\Dԃ/OIRz5 =C]Qu'ࣗ/ T e*b h0s~̇Ȫo>+ib;AX)0Yf%YŁ =-m7$Q\J IυZ 7fFZ'iS*"u?߽!mg ]^Y}6C?Sr[n GOS!ǿ '1صbXfu*'~  }h !.h1((5@E*`øNqWh/nP&@kQzb_gfaoMH4H_%R{Ͼ <`cho>~/]M4<ɪ3ieH8h1pZeI$ AOayL?KԘ2R2q[<^ X㍧SP.BbVY%4~VM*V "6KHW"0)%H\~iHcHc)u~Skg)RnWMAsW(D;o cw|zvNt ;tTqAA+荴H:&0 JC:դ:k\ y ԂF]~{Di&?&Ν⻹î+bzZ 9mĂR:)$IwDMr\z6Ӭ-Ph ĘM"J ]])at4A-H&Z1B+c3~[<Լ4.SV1((UzHcK})(Ҫm- E%N/2M&g)>1Tq;MXdVr`<9F/Z{@ Y e֘% `H%R13Vg8|vmS+h"s3j J+^xh-5L[)4Z钷`&fw Ȩ"ůͲHtH('rJ"*Z$vGhxIZ ^9q=חz]7ֱ_ ; V8 kgP$Tke MհHf^, iPY W] yFċW3z*rB+8lX#.-уlrZ |Nd@D[=ft42A<%j̮[TbP|- <7-MgΪs6vFS( #fNz. b̍7;Olg`# pJ Pm ¿Clzϗqmm]Nɜ*TDDpKHJV,yN8zy426q)+38%R.epƳ+g77.\؋ϠB4[FqߠrR{b{q@JuN CzK}|`*/Q(V̜ H[&t_ZG1_.!J9Ro Qab%tx/hQjep0kf sRaJ?# e— 8S9ٍWp q.#UNjrъ+(2ZD/:Rm&HU&lݾj\z.niTChl(iWѻogI_`5[Vm^^,@J n~L~64G_X5SA'qW4iT&։\ڀDc5|-lWj*^ d) lzx"uY%Naq<4,w? SX*2oZv|NpΕr9 6;M s%Z SrL>~1Q+5WW&&dȤce"uNKª 8&:[Lh z%POі͊mqg<gkq|@^|'Ws LR,*ŅG܋eXn1tB'f~ɛL*)3zn6*j` SjJ:'C5X lIHYg˩`fX4Vr`m;M\ F Ǩau#aLz< x72Gi|~L[=12ZSn|at0L1)rpx'EءhS\>gwn!9j|{p[TJ5mLNҭ@9LU7tu4<q(Wތw: E>2wO&JlmfeIT)y? 3ܷ"H΂~o"^ 3 ed033zz{u78C-{:y0r-Y Z&j5Eyퟠ/0ru㐽 _KѤ?}h\IFKXȥcR^_O;މ'}ֺlwҏb,Z-[`|%Ը@QTy 5H& g"-k=;{mɨJM91 =xnpG(/ܵh8n2R[ ]aЈ+(uu>;!BPe eWǽ/܌BPfh.Ѫ1|piUC}mU5ěa|Z XrdwYledƝ.Luq07[7砸 Զ[0XX㟆k.Xɒ`iD\A;`s՟l![(0U-RE@R\?gWQr͚RӰuj UЎvMǽ`22؛Pw_aL]UX&kiscz¥ب0"i#7zdʆ 0rSP z_}'"O {+ƥrJƛy_+gk̡@c-dN೟ތI%O"HAV^N,$i։*歜=䠰[覐D:x]euϤG/x=x/T±X9fRk6ZجV,fuU_]s'mwxNda/l^g e; 5$Y\|DFRa]~̥G.tu,vVi.+7& f̵su^k`|tUxJ͗l.XY 6vW36V:g~!FnEX`*^0qcVvWe;^+G5Lȗȷ,wdz{. 5JW]yVF{;4=X5s6k w}$y 6OHh7-w$mpGbzk\wۼj8=gQ)xRaՆ,YUZ < Cx%uI p ,:\(&ѱ^n;S~хG!Gp=nl 4_KnH稫:{awCcռj*Q,+=6M| aWaJKdINh[8M%:x-k̻GKXmWyjw67aakP^k-YXoնux&Y+-:7WrlӂSiШvDy.I> ŐOU&_ٵsS'ǟ=|XӪ?'ے#(XiC̴:ĸvluTKLMێձ *O wowNu(2 V;4WmN8@'Uʽ%؍۸DxLyˉ szCv&|o]hߧe xUoG *#,Vhv'4VOʒ nZu[k@7pU?sc@< D)uv=dc;aw(nPk2)E=5;I9UR( p_jhU<4ϛvpڒӥ|9eՐEVxdyqCrS~`63IAjn>pQV43u- 5yG`ps}y'Аh\^u,h)TY> stream x][k0wE;FR/-jal{Cԇ9 (|9NO=&t0*h;i;1_\YvzϹ(_.%l\oo Y _ g\dc/d38nmPkНl斖SJݡ91JΥPèe V,-aqY> stream x]Mk0 :v!% m]vsm%34qCb+0 W_yUTJ8B#08lBnӞ~g?ǷCv2>0 ՞n!Z*0bW4Y&`" >س#Hbj2.x/pЌaE/ -\d2cˣ׹<Mfiv=- ;m%8 KBŤKYniG/3GXɘ AdTxCkrG endstream endobj 489 0 obj <> stream x]k0+ޱc ] "tVCQ[(3 1gCシX) 蠕JXh9BT$N@H*ܼgDO#D^\Sq߽ܮe2q Bձ}Z iJl88; tOwTlny:h/Pe.^VZ`GT$4,3J{{[M%i')Mv{ۙWzG[GHλ¯R#JWt) endstream endobj 492 0 obj <> stream xU_hRQQ'WS[ M Yl#5`0w*W&6cشFCHhF/+=ߗ =s Snglo0g&Y[@FPQQ1P`à a(<{:X[/za)BO %stNx?C~:rMѤBbC\'*!0'LH&&RM8x!xfGB\nsthPZGn>O|b]A8,"`  /P OESvG'\Um{L?ObWɓLVV*XyL}/[2XUz(}1~$Yx|_+ʸM\2.̾>1#h=mV`&Y+.`yܥ{L_++bIdfi(%$H.dSIzJ]sGMJ4bu#^>R|%3}`h F^ :w|E endstream endobj 493 0 obj <> stream x]Pj0+渥5 $*)-u=1& $xk졇 o^^$Xu,DZֽ<'j8yU$:8EfGRX˶HH,i *FPmwҌiy 豫[X[MC(~>kl!q endstream endobj 495 0 obj <> stream xO`ۭ@)M"4#Q$$z-ҍlŲec-ll]7`/L$^{Eb_`ڥF|%0EѦxz3jp7؆mUJ5fb&i3)y #b[;u?ǫa=-RBy6似az >q}}W:osP: (fL&#tuO^`h~̆+v cGGrS @8t"[=*# A qdT+PFU+ZS`vf (RP4j0f5_z2Vq]ʉd r4jKXcؼHƁs>*ȚdYD/K w9I'@Us9F μ)Ie9m]2z|Ûw{ix>nvDkvQ) u lH+>sKFW"nd3V5 ι FGrmi707ue9 H̜&ODV0LiQ@ "In$f5Z,_˖H_Y7w*6k-R#UGòPn,;0. endstream endobj 496 0 obj <> stream x]Mo0 >v&J8 Uϐ4B_Y;$y7NZdgpK8 vdf>Ԋ9Vz@pJv|W[JV"+iơQo D ا{ព[\ .::Iu-;dyPg'R4-5t]>,φ6$ĉ8QHjC1e[qA=O`\C/ajTV_M endstream endobj 498 0 obj <> stream xeU PguaȉuZڑbjTkSl"Ba! z@B@6 +AW-cSgzY633~KSMVXpELO m &QR-M&4.`2EcBeʏ7G GS4Rב*EL]Vf$)D͝;'BRi2u Blդ%r*'4b0#Z+f2 iYoF>di2s4tQX#H-j2X&Mf͠gR\=jJ-KNQ(*MF8j,5OM&Q<%P|aMPqQz0,/5R`Q/B(bu=_1rv+R^XG&cNz|uPJwnd"$H0qఙ]qrc>fcqP܀<@eKP f d>H V]Xh@ *nOĂF!CyIK} >ֻ1Jr wE6t) nWbbz>DGgbu\*KM%&B^; kdE*lғ p=F2K<+Kz+[F}Zu[x%$tG~zI 9O )ףoka?\TW>( bc O{TtBsy1quVE | g[ЋZER)צ;y:ýZED]os?|>?258xϝ=Gxk$Gf}8tb/4CW%L` "#h2v̐$%/ Le ֙rm"Yp1=>o'w寓&Vʆړ`swظ9C%1Q,f*7= t#TaI{ڜm(rL[K6MoHWħS_ ʪjPm8 -]jIUiCCCV(qnkO3m. +pxFs :cFjz[ Ǖ 8Z{:΃|exsPZ㖦{m<(2&<:>':8#pq3/ j1a\VCJ{G4Ѓ/\㻡ϴ$ސZX縤ޛrtx #Y\ *N6R3+TZjP*#ɁmlvVurZ6%Yd6DO(ciÛp[o#q?) wq|fzҋ4KNoXSpQ􇓠)8 /:zSC+]ly‘]j-qŕ!b6@azi?íegu-ٞO.;y>Yƃt|@rځߨչHXj ;WR }jsf[ksS7 >1I=~/ ʑ_ x:"O"VX`SxGxGAs1d endstream endobj 499 0 obj <> stream x]j0z96` SK҆89(KcWPKByj19 7'uobZg($r 7&I}N~~zi81r6[Z9((K]ٚl޸Ǿ G#k݅HhJ ).1q֔rDRieT%+PCe3ww8#瞋ȅ?s{"2(?!$JpOz endstream endobj 501 0 obj <> stream xMmLSgş7.Q900Yi0GT) Y0n vZJ/`  2 3(*:6c2%f132f!^->;/9_PH&CE)>YPՐ-2z\܌-U"Rql+Bh=:ը 1>L Q-:5j&%RQǛʌPiӒ&g6}9^\d긄=FAHNQ͕j _՘#W`4ՆR\frVe1WT ˵r(yi) GHbгh#EQHPZ^ܒTI@lHB7cf6R}-Nl\Sl \mppv#%kd7.4_ج?m ^%M8ls9־_HF }d''쭭ϵ5a56D5W's'b<yE/ YX2Ol+*xهH1ojhr*W(͟xw)N׍c__ srB=mzL}#$$˓&uL}?euN2 LGhGf<~ZQMzp)o|I= M㥀TdH 6'B.Ǡˑë a;MqƱXrKYяXwtMߘW0\wwax/ OXlטnǣ˶ ='t]_.t/0#Ĭ9 0SO42\L/B endstream endobj 504 0 obj <> stream xګ?G n endstream endobj 505 0 obj <> stream xڌ ?2THERaY4cߎ(ڄ"Oh:rM .B E0\:T$4 u#hEm8ǐ"'G{Om=w?eGGh:.@D` nD[1KTD.vҍD+G6-}BO3.|B{QVaps{̾}J0_IR57$?pq p g6:>nt"o>8mg;}$x/ "smFGI;4pg^ BN239ڡzNka_*]8 NǩASC:X<|^F 4 Ox;~Ň)) q{CE*9IN1<μ ~:>+b}q{! ~ ܵd&= k~ |9>j&H*xx^I""§4d\`tČfnav2?gTe ռuPaiaGb8ˠ1s Q?|Vh :XǀsE:z $}̗~>JEè Г^nŋz|;ފwQ-= j2\OM%9% mnr>?#$ߑ/0!&t11w1 s*Zmxv.} [T?:njn+,"!Wā諿4َ$Cr&y?wI $|ۙ1ϓRU.)茷wTOċ!f!MܸiUmVRg-;#‘}/@hT]>?#ϑDѓEApn!z}GۀN_VC:nZ:Lſ?ƛ̗8RT>6H z `' tɠ٪@M t){ wrԄ'QS,*5zmC2Oȼ43~VO~n@K9''ae5x6 Wƣ`^ErqNq7&d@Azaw<8w7:!v5.{!Su-P(Pw,h /3'@Og4b ,ȁ0s ˺٧@&A38C55hUY q>%ԐIx,İ >r:67NԬ!UuIzX*&_M }-hK2aP+ ,xѕk^h4v Wϒƒ>gX~;rA,x.R]v\.]4ʋ+錤 f2Kgjɢf4_Ej;{Nd$ |^2ܢ_ Z|rHy0,uMaJju<.d|v^OK?;/P8}V.HN'{I/rbcq{%Cz@AM?3u-iIWIϞ%t v՗Jכ/^+m)QSιؙVfUQVzaW*-X7/=pM.%4[[/_6=VȤg .6$8I7;0/_8_xi(3񁾮 b nn%h~ 5}juH&\QwBiM uljՕgtrɑX$`Um5!hO6#66G%WMuΒ]gD:H +Eܟ u:\+9Wr/]]e\+ǕB8&j7uDJD7 ZƠR;v'Q{^ͨ 8*̨+$Q-| \q I%C|>r;PiRY ~lL |Dmjls,Oȩ1.ؓy!+55*l?utRb'굛SuJ5ow!^zwV8=mѲBw|Or+9G?`6 '!ɬA3@cl<bd6433=n BrHKg@*rmSLCIKYpC}]cc%G㦄#3'zB+svUE6_Kș2g?ɑ 7<^LjY89O`V:ƟǽiנX<2zcFg"L,6,>,a?c~{,)h|rv8wut %AW64vhd cVAX^Y*tRrK6kf1|s5 U Xʅ ڐQVKa"a +ympu흸<^?R8 8}ݏO{y d]pcCe^\|Y^1'v cPXG(ŽH-#?C^1Z2ʺZM׈yb;$`ᇑ{K $A.o9TD=Uyּ$YP>g-ٴ;Ԇޡd>ßfӹ!k\\Z U9d(,RBFӫfkg3?:{̸ OˎI3&.;AٛۮZgq ٧{يhgo#, na3HE8 H1<#ہz9ވUE|HGx٠`D^C4/2Zý;P*"*%BSIj97lЂڀy(#Y[RIH~\Z;$0MaK=ٴ_/ .2K/~˷~v[{Usr07r`-@k ^\$|_jT2ǏL9~@~vt?B,#6o?47Γ7^0{C^)!잊BRk@3 7RTTr"1/#jk8hGJ>6l(ldeP &]W8V;"T2/*0z̮7W[` MC*\ߙP.?;mŚGୟ LtؾtE<<Y5o]K6@ÈrXQb 8!Bk2MYs;(jOrtըZiQb]BP.#E=c-107jN1^ |ꪖXl>SQUsS_*|,G}:T2.3ڼujuI~Grl0zyxPڼ҇1eI\dZV%V155,Q xu4&({J!4{DtKp"I]6)KXv[S-5tV7~ZXJwSQ珏IN~}h]S,2Dq3d_(3l K`ۻPQ)=V[F=q V:bjڷ]j_-{KJU_1b~a5"v,Wk-wGxnD(IaIйKZ hG kD獒$$,p[,D00&6an-YK2 {2of@tZىH)YtX_lclOTtLcBLuC`v,P?;Nݡ8rm^jG6(?s`eRI p=nZȽS6FOܥokj#[ 7YPc\a80WYʷ0j׺lqbpoT·oxM4_3Jh6w %V&>Ax|..&kv?Wu,x-J*p3'f"r'T q/> I<xM,D&!ERM4DPJD`OEZ{$(T4 @ziUy#x(Nf>Uãfɩ4;Ca90J)iη?5e,!P8{h l`7զOV%\Q1抪cUQ)H$J;B ڤj2 Fȩ@Ī5YΪ_rjzK1X]4[Yh,/טm?ڷ~gu|csdӗ-nj2~#d|J+Y1zSMg؆+LklbUsw|ŏٙGp(r72|)Ws#r ^6{n6Vfeueui3Ƨ\?vө(ӷDbP- Q6i;fLk$f.C1jb2M[1ktQ\kͺx*I QCNGKϸ޳Ov&S[V.fA33:`rkVt>v5`M78AE19@R=7ـ:,w3iw8rܵ 2 ֨937#lq'8FP}INv$%&W&7$%Ojw>v'!#1O]=(+O}Ui꾕l$~h9"\"~T-dP?P[JZeJM!b)DRnc1Ôl?C]t[#^bcU+c͏ [-7=T_NfƌM/֭ݩ3KlOzA5'Ots:IQq!<1k( 8tBTb0H(zS8l =`F! `SmwTUDH0) QT:}L9IjSmmH`P+m%BSV_-XҰD2fɚ.EWM3HqqD* L- Ӎ7}Ngh}ah~&+iueg#LԔ%tWhSdS]: *n~~M(CU^}$r$vR7V+$dwvV> nM>7piLCpR% LDkMC]n6$cEB,8mk |Z4|_ZO#ŒYbh<6A@cf1|?hDTwQA\'TzXh<B$m,̼j1̂q $▚Vܯ\Jn)GFA*Ј%uXU9Y8\=^쪕ȃZy?QqޢUZ5vP+o=W/~=cow:mbᓖ֥-xὼfR"KmQvk'"`-4 7]gSy7CjX'*E^A[B-Z1B9:wqp A쉑Pb_@JCkRȊDtˬ2p]%h8cȘ:s=sAފzݵkK%bccֱVG,H67"y*`uD) 5l*-#lyM-œz\؈7~U2~t1=0%NQ (Xz!`%}!ujqRiɺ> j.$DȜ0 AuN*kY*l.؈Pu h7L{QcpX,[-}{u'۬30LjYÙi*)zBNȉ)=My|596SSFHrU!@"KwM˞fK*ʿ[)$%%UQCIw9%vTE6gtfN>RQ1Erg 5z5^tK ] ]u(ekǣwø _Yk Y7@lljGՌHZHUsr9ve9h/p>Y&0hScb 3Fl[*ȇ}V@n˪?G$J%j4 $4Eu+ݥ]-|ۭl_ t夭ysZ%7 !t(lT p*m^5/^{^Ч *tv ? j݀%9g 뀮e݁4&[?/sǃ_0:JAL`L l" egP7~|ְxa.Hig'_8BXl!Ѩ^{~jo|%x""*>{7sv92 ~N_/ҽg}}{?Z q>n+ u]4qU%Ak(R{4;nnN^cF4jZ.2΀vgvagu`p=5&Sb ֪VRPك|<07-tD0[CVb˔ B͗uN*]9@ mA>c(x^6QX'_;4Prd1'bE^$d|.Г0i,/,q[|O,Yp KkƬjY491 XSN:Pamsᝯ,<ؼif쾮ks  .l)>VޛdWPȀ Q$ Y>;-wϹ %*5~ `q"؝jQ2Ra.RV6+>ÿunt>@:cXmD@ b5#wrbĔP Cvy\D-iB":"i,4I)RЊ"kE3e/[XI\ _Nѓ1lYidq.*lyMdarb݅ؿƜ(ߐT%%*ެM0Om1momЍŝ%uƝNn^w'c?1ftR /q/n(!V3YYuDl55-5ݺk:tul+ g^, 1F2\7bj l/-ϑF=j+5F$=)v pz3;Gy>/.> MzqGQDZc ,\ )T 0@A/ ^$1+TEG( 7Bf{ͮ( ߑo$s#eTڅ捼%뀯pj/*a1*4WKHcz;޹X჉ ]gK_fk|fT`j\,\_x:}|“ OQ{WK U[U]F#I+W DΊXY^I_[[#%{S:v_^61ɻ* ^(Y `0Z-vI7Hw9Q?(ϊ /vD攈EW_bє/'$pw#)@_y8,zke5JT֕g4Dʒ`?5((.@ՖψϨ )1H\nfesTL`qk DWٽ'VWq IY w,DJ2tސMj Yh%L|t+owaR dxbY>wf]_d_00'{ .)c1=Thq(YFv~GٲiUdKWYwĚ06aKkfWڜ($#U[[++elً 67I㳵`M!!Cyq{YG"izٯUͫҿŬN&z62RC; + xf)8Ǽlz[AdZ͚@t(TqvYB`;S !W`OCHRy~5=, 1h"\_j^_k39yb6{^/lQ*]$%~R,"hjb^'ߴx# ,-y55!o5:%~{^ӞBwOpENyɒ;7bHM=}5gxhaTik"G2͈T|֌  .BE0B0H Y0%s,jJvƂ۽͸>PwhCh{H:+|"st/uDᶑH{*da aEΖRDa;pa?在-w5)f5IaF~mĭz^}>RQ31Oxܣ +ޯS&^16<[^ !&RhF )[B*H)lv0iXт?"lṡbnkkj԰5zpDw%5=*T2T^$+f],5EQM+VKX7Y.ʂU62cYc% djioxtJ,P}%~ןl1v}g5h%WO]Iک)pg8_9+bJ _8$o$sJKمg]yr9}:< Ѡ arxԂ. U.VW&jWUXx߱aÁ^PK .k"Td>T[YU 狛:,KFo逦:QaO$* H^_vnV*({WN.^+ʞ[=LT7 [k}qBpz2u b :O- {񺇽2)RȧD(Y4q%Dђ?x-MCCm8,]5f2ہ͒G#eλ|Jh@)!PVo]-̌ E c6dZ{9U7to\Dm`]ءqh+پzX0XDž ]i%jvx/:8ڂk:єhËSu[;Աcy{SØ6nNOJkҸ6LA`QwjP{ހg{x%e*"7v;&\h UҘ+`1t` 0pmZ&a/bGIvbJJ1r;>#r֤I#;k3Mk^>-ř_;I;Fl,<=ˤbKzfۊP( 7@+:ⵚW@ZR<shѾ-uߪUq0Ne+Qzu0"jbe1aGئu;@F)-2EmdP|V%:mlGvjv͛p8~Hk߫~jmMMtMhZy=>k ؾ[Hc*ݾ۾ʵñ?rni725auV+z dUE*J?Wb=U?{7Cz\jׄ547kTDӪY٪y\WW^iUøPFL,N'u;Q.&n9̘!\J}n#_.t&>&`UtUGjl EI ZAZ,<~QDnm'8Gþ$jHS+KJs԰2*3yvsi09elG90@r+xl2 :K =×.euxn%rdp^oZe6zB<}%ZNI ʆrsLwT$Dw/'18&2{B⩴Xe2͟O,縉گx@iABvu:i>*T&J]安K+3iL2&k|:2H&j-JDFSHeIc1DaM0~3udVO'l<Qinl֒ ΈZ `KiɔtDo=]Wg9]oR&Om|xx]vyGM"Sm~?Y Nhy{-%:x rLBoB#Zܣ|*G8WJbuպUmpjdԂÆ: \r D lxl;Uz Ӂh%cx;0C~h~"9atĔDob~T7nb布K^’%ZC͘-GtU1k*;[7Â*0Qb;p*zY(ͤi/&Drq{"돪q/JpʌͿ<rF5a(Fs9SưѰݰǠ`Jsg4I>b5럪L?DJ\쏀~ԓȍD7 Ƈ0/ w4J)rª lv`♯D)%uv]fW Zf(U 0]k0}5]'4Wi kCgiطf>1j(4%OzsGUt/j$>|1V6Va*&Psh|GOW?ݩGƄ 7.boOrlg`;Sӎەiݙ<KvC M9]a_6Ls]y6keVǏw䋧kl-uUBNSǨDnܑcBcȘa6J#|'|ae{,SC 6gBñdVL5U+U1UH՚)`6+ L7?\!mI˶]3ɞ"AQie@S㺼--YN,JL]8uMu*=z nq>u 1%]7qZ{Uգ̸oۗx-s[5uW 7/gW;VV4.|*5Iyڙ5 yU5{n}+W<~pt[B WMXN*O!jVXtgCBI v!Dzj:VHDU!#/Uj>qadLyl㑐(H(IH('HP$a܊܋ULF&JM]Wdl l Tjj!W@D@myK mXކm%HPj0Eҩ> APJ)9 0W\68RdUVĕ&q3`SKF;JRjLS=dPU" <*.]r>0f.\ڛ S;sZDRPj6j lM 0#&ʽa{W*rԈ\EOZ/SspG?PPsJm`ȿWقVޯvEBVjRHB ;&Z4fZFW[-:-]?rI $*.WoJas) 6VBz9$`opOp0J;۠p"x:L=Hw.W=:GxK4jlkeyR=hOaWdBoA*!k||ީ U$#{>|idZ>EQj0.4h\chwqy}O^Z+ly+1 {&*h((cïv HMQX0h˜@ҙ! 9PdQ=EB$UFB)IbN]&;ț_ 0 y`MMNk`7HDr:t|VC60Wcu<;a];`Zw^Z JomTVV*=M7*q:Jx5 L\NEG3gΞ —B9%Ÿ=>CAqHW8?CB%K4ݦ=6#Xak%/*X?UgJi}7 ]ʣm@6;hQ~_qmn[Qp|)h$#"׊"5C,yLK`c ni)jVFE=EJdet\zMK!C=A+vXYOXO[Y+_pu*cQIe9^QWW|~E1ϧSlom* j ɺ`lCmh\{76y"!{wH* ёP$#!$q,FBO:J-9#6.G[B G[;3v699s̜93sQO'~N'g"pgݓ#t-u/?|x!`~M6{=qD`c$%?LB$6Wr4ޚ%[>>)oV%x(ss]ĥt .,q/]Zk+*!E q2]ĿtEK S)$JeeR()!IͳLjdR0Iu"gn鲃IF+atB6]eZ5YȨBb".ڰ/dp*>53A"BH\蕡Jco)]_̷Ldߓ }IRr"U` A.(M|I]9)AFUP$ "() YS ߇=K#PÛ`0(4:kq8&nQF ҁ^]uAҹYg[{BJ64dz9(r4g*QGb?@%7)>,LO=MiP\.&lY΃_U~{۟YuwiܶoxU7t)쟘3ȇm- Op.{ y\fͬyc3 mrctq;wANu!0r8g' w:z/DQÙS[gW=tb!/KVǏ {cmҧ:1]wrc]gui*=ӵnPw6=ŕB|3( *<gÌ-XˡGoBc9EɝzLB!):HC:^g&3*,k O|~}8~X Vj6Hk>\0Óa& 3ash ئy6ӷ< l3Yk-ܦw x#pyyYR| @&IpSWBx5zF#`[6wˊl\}-dM`-709ބ$|3Ĝaegh h&([ r ~0Mقo5P]߻[gvTR\$KͲM\ܹyDO=17H$e9y `='W EY1 }uȞF֩۴E ~{5'"Y%s/1?%7布Es͕b)*+)$sNq.a>W3;vNr)OYZ^٬ܭ5uw:v_دs|}g$Wdt齉Wߡ(3z}ۇ%ěygpAt[cq:nMB^.U pqJ2[D"1"O&2;"DJ%(JNdDȠ Dkd1{z!4YaX3/}(1R"*&$1H~`æh1ARb%ꋩjTRlt>1GJq㏎I4N>%oar$q~/qxȖec5&j {,ԽE2>6u=E-O4 6]&{$<{g&k"Ը 7]6[jE{7eYa/QJYXm)L}Gpnieby7l`z_J9r. uqѶhKO}FI3 ZrK4쵌 ~ZasZnۡ:<z z"A2"{ԭ•!pJ4SAњʷZ%qpH WVΏ^xB1TʈAL4 O=bLݑz.Ŧ}­lJ&ڤE3LǓ?IrI"\\>mooeoQ̾ UVe# `*ZNĢUL\m*) Vl(_eE8ztn#9:n҇3X_0Y!_vοP;5q[Ϫ*VE3`{y ueҥ),(iOו1| cбK"m$nYk9l$< ʁ|]QWrVou]Oҷl gn=ٶw/l.Yz[`:bs\ըڿwwXM=쳂TkjIx^s}n1N~Q)X8aKV}.gZ|ca%6WlV FS(LHo$\fA [KL (sա>6K@sRmHGMy7s! 2C<]2"4lGrZ shC{Cz+WB?o5A:"b!(ʑv4@B9 ۇ~;)co6]ƧL7,u_98\r_q ;Gi2&YB)::]TZhmmLOkJפ˞H-~ӓShBۙ"I }(s YjAcZ}VYԏh4bA!/FM?qL (KG3}2lBh]F3],]rvhYtrx}Ah16 ._hVʷḏPMFsTD[&4CqPh7h4"Doe 24SnPa/UZտJWiU*_UVҪUZտJ' }7d)mt5Ciß(m!m3i4ǘX2PGT/j41>Li'ѡUOPEci4t.L͡IMoh}{Mպȷ&UaL1]dLձ)FJɘ4|D?k4$Tί4ȡdX"˰_EEEbG+ PjG;QV4F^4DSV@lhvBz(F~ mE#4"pvMS%k:Ar5^Pf0R߈6 U@eJpEBjB ŋ$rImCQrQ/ڊ> 0J5 <$o] i]D b}#GyRSTDeڐ׃h rI(wZо@56\K^=\yt S %jYK@4BZ!rTuЖITOD>{Q?}M0켎AKk&ղËrwC-]Tki]]^^5Nxcݔwn?9jQP$tiޓ+FRm)QپPׅ5w?I^ajt-{.oE: =Q2J뛷n"_k7\K{>H TtyZѬN: |c$i5 !OQ)]VV-ZGH+;GJ~iCߎ#҆kzKvHz6 X>=_#yɬ3<ҤҲ )5<82;ZLmLRI7"uJÝ=;{asi.6v΁49Rp_H邀v4 w^7CZ#%IPp@kĬk;Ǥݝ{;9#PQ҆{i/[424<=5JZ{ξ놢RwP?T]R}\P}$W>8пWK=Rd s_IygTE4zKMRڂX2ڳ{jvsqNJ=ΞlvЋL =ư_hsʵ3zQn,<][N]ytr5AR.ZKEK=Í}:]\?;k>Wb.VNZ ~c9 r2.>B*x1D[ʭ*jNq-\$2z9BˁXs- xq5Y[K1"8ڥiΒ+NOz3gc(49`aVɜCyаTKEKq Zrvsd=4IΚ, FQ._"7L—&JJ䀽lSZj\1.d!#xh}J8 p$ K+Yؽ5쿳3>ވUŦM e݃2٫(eBCh&bM?Ͼ^\u <<;R'Y5}NC7A-"i(?V@(;ܐw ~YgPAV[z>H,}4l:# kdy} `ނy -h[`}r{ @{3ϰboM؏0ޘ5HnPNvg_Fh+<~v@ ~-ձב1x`oj`gof-9qvB`mڡh+Kd-kQrZŶD|] ]_MZ-m^o%1Yq/=ʶg)"R䒂յ鲣:uR+jW+Ғ&ʘP 6.I6uy"i-JVUTuF:kwwiڣ4p`1N{8NV,m%: S [| $n` j$Q&Уcl!KMeNL`ɂ [(!q8sPh387䊢$AP8dXxo7JF.!o|풟VQu?g5Z^umLJa;˷OԿ]k=v+{og%O$Nrk6]5d)'n1d,')lf2OY͒9`>l4ϘgͺI~Oy]'a)}^Ӎ+_RC8 PNsf 4 !!lT2B@ρoC8@fW!m WXÌ=,Ƨx6|2LgLc- m+Wh+_к_@/Se2Bi  aByY U >N(a B9 9D`T(魍sD@ $vv94ރ2.9XwQҔCx?R6Pm|Y9%0AuAnˑcpL3*}qyBeUdXн~kߠ4 ?ACA6 Y>65( ɧi: wɶwa aCaaQ*_hMW֧ Z*^YhкgeIa쑬-YC(YVvOV<k~,3B(+5)zq5R(EF@u : ȩ%6O"26;Qi|t`A~}O.@Oi68sjV6] ئMN&'nٸy4!wLo jnzLw6uRʆꙫ l̕A$7M׫Laf=e\eZL+)ӗ P&t(N+)ME" 7BX`icj쯓iWDPab׳Qg]3'Լ-mkvz''K5$Cd#۶w$gPO@IZٛIPܾyjӤ,5::ns^]-U}DU@ԵԵԵN^Gjٰm2kW˶@Ar}^:K 7~I+J6&I\$ɂqiAYer4mk#7::R3F4F 4叢sʋF+6O6{șYw':FP"VH zM}7uͼ{Z^+;C=Yß~$xAv~d=;:zx?yI&O&*#%FF聏wd@^ϫafRN&@Pbx1f"j9 "~t?Z| endstream endobj 508 0 obj <> stream xګ i endstream endobj 509 0 obj <> stream xڔ `T7~ιkfΞLd&@.KeKJY *R*BkU[WlպnZR|Ϲ3A{vBZԃ25Ym޺ZcU\g^T,\|/++oX5Br-Y8wuˏ tp}h0E!Bǭ^rժ5][P+VΟvZ7Bqy5!p~W-|关aQuZЫMaj6!K"- -"f3='КpW5h$@>'fGl4NdGu/lFG, ~x*JB}<) xVxMȿ{?Ap~?O F#dFЫ#hz_@@7 C;jZ=!z;Gг,F N7dFsbQ4]}lUGH̨ 4AwXkO^Xރ5k:˟GQ\8ZTñh7< :q>gvs\cޚ?^VCyxYs LYU\ Ѓ$z G?з 'Pt9V:S EW|7ٗuܙ]@(}gO{\: oix2|^8H|11gk9._w#<7f%݃^B` xwo02Gț-Ve'syE,jXsqyC9w3kT* Ie:׿a9x'48<rX2ςe.Mf|GYvOð`y?_b€4GH$Ih2L!WtArXSe3/0o3߱-gl;]ľɾžǞ\ɽ{ ?_?ϫxUjz۪!t/ɿ腓6@1LcV0w23L{#X- Ev{,i ghӇpemM`~|ܔv⏸-`O z./܆Z w-?z q6}„P < :wP?B$80<'p0jo0~Ѡ6G%6Bΐ3I3P7hfp dgCWMbiM&ȉ?{"6wL9P;y Ճn|K+Uc Q@{ɀe2Z@Km# ; ΁~ *~33@N8K62u{Co@ vlݨ7 =̖C]pŃ`ek -x@eKFM Z])8?-FS{WZk#3}C|xQ;ї?;zv6oϿl@ PhX*gxJ.#cNPXW>v8v.")o)$BH5}8bxðCjk2T5QmK LJ^8V xJM]16jZ1T gxH[FձH݁&kZlANhQcpo1sl+m69m3kv̊[r/յ АHᲊB H^;}Ϩd4?qQDpEͧ،yڣ k$?lge|ezuV{nr9S*cѱyoGiGի ?zdW'e<œu/ÖWV*juDve.zΒV.j@8u5E_+B#F3Ȕ>o-.Go5LJ_WȞ1 s\+]][]r=z/.51[,dl?ğj/7UfGu2A|u+Du.,xtuO\rH*Caz,BmV%Jφ \ aʣ3]vk$UW<_u~gpe7쥹_6jf[ _kUc%S'xm֭ Knw;/5Of[eim=k~l}csrܝȂv&rnhvMhEӨ-=i?0?РP(WnǶh,JjD4fuޅ߬y䞸!22iяp۸.unK>ЇJ ur-s <@@|yﱵ>?;A&"(^I*w,`hj[Pּu^#M_/JnGb;!VR6㕵G Ϲ=rś_na=,Z3vl Z"H(rOyp<5iZ{7;o2z{F1{'}uH I; 8D֯ѣXm5I Y|D3SW!C-'Ԥ7'Neu Qāف Î+µ]@"U*\{A|aG+gŝ.}Ϭ3XWCnj Jn4m&(Nl'Ua"no0UZ1y}IEOx5km3/OxxLzJ/1=lBUnD|H2)]K]a+!fU6)(ۈ/~=$$Mڕhid.G*&4"jj PS3jQ_@# X %;;,Y&&xIU$' b3]gڞnGvDgN(bj$S$$q o-lNw99=}s{McmQ;:\']#s]bd8H.烏~ju ]z]KRi#fkU}s[s{˃[[,zU]{͜{H+q5j)YP#@P "]$d5 r;d? ZS 7p8-Gx%zH浌krc5~HuAtUN$U"%呕#GIޗɟ&#@tFkŵ;zX Ң,b:Nfsg56W>* 8ňT0௸;5{L ѱsgޝF٬v%r#+z*FM0DV q9}@"O/ۻ_kI8 Ä'WE1:]%4y9 Y'E:5utu#M -3732ԨPTo |2|4|ʏBE>2ED7A("ʒOp*d1h,~PHfJxAQ_? +R-Mp`xCDU ~hj#{|"k ޕ9!Gdsbq)|~A w4ė>~s]BI_TcdRDby.bF5/Ib&icF]ɧaPD Stu%ZuOvYRXעuRΪm+ՖI6qDr/ Lyh ,a'ngٔYw:=cb%kw<$>ҧSo|ף_ ңqQ^62M5cV#Vgy+UUU:X?Q?$9̫8Vc 1^$kj#bbQQ0#:ed*"-jPx*OE7%q@wΤ̦[ }F#`Z7%]2;i`/kޝ wNjzNS@r}GYln-m6Kng(QՐi:3=0SZ]ͭn"^#ЩQ4-6Cf(L L//r>t0,ME?!'IO=.ԁ{Z>=Q%D<$Da90uPAOf`TN=SMcR Y^_|}.lvqcfnټ!:[O鯶?O>Kց1v|<*莽 (z0) zEElAg͟Pq cԣҿ_!)=k1zp,? 2 a='y Y|]ZucsĐdbEVf[],>C>E"i|ZԎ&DSdbQ|իU<[]@IS.Љ֕.&E,CKA׃̹P:Xi,2.أ{<7Fz'ݏGvyI;]4:f;}Ќo7o1< P=nFxB|26; -Kؒz|}luVG#hѼպվ.mn~Xga 헺/ _ľ.UձzTVscsXWstcїTA隂,55jNհ5gzPzI9d6pe?EIK)lWBi^H&;+"\U2[J3X GbJ* ^wj')tQE/ / /NH9,(j5__W7ϯWW/ZSSU;厫VG޼k螴sum}mkfwņ)K[=%$lX7s|2AL8P %ZnN}n~mMZZJ \)Ŝ㋰HOZ:dde`S6%7juƉƱ8Snm-3.V=&Cqɼŷ>ƣ/G}_]C{W}+W66{2 *jƣ{@Tfzlk|F1 ޠI:MN2d+% D#cA-x_אٔ%S|ؗ%_ˆlh110{p3n (:FcMM܆N$c,7^lP5$I864.扁>ݕյO՟~_~wJ̟TE"Fgs;6_E"lT>Ix "~ %PANB|[fߖ}žp,֦ﯾ/;d={>K>;h\\[OЭ6G&-KP|j9S~ IDņqD_-26a{ܖn OĭY$"~:U/SĈ*ww%Y0>oJzsiU^oO3\ߡHq_ _[sokɯ ߣcB0 O9ILthy kjҸa'q*) ƣb__lFMƑ{pXe+[}/R^&C˫,CAX))b_ޒ#BFZPA"n ]κg[HBs)CD~@ѭGQSG%D0~E N&+I@G!ᨣYpF&3ӇUnCx>1;iTUqM3\fb4Nqi) IC%6$.r 9)ޅQw'bCRMzH j¸ZD<.*S1T́;蓁$69M&>:G^8eUסgguD<5GGjC̊Jgu6T7NnJ#k5m3V1G}ILĒ|161ko``z?a11d$UM!q)MA '6:NT9!`%ڻQo h^]6} Q( wZܙ㹧ƍ2rs7oɽQ6m]{ONҼFnz%jqur+%od oro=oG/7ۑmbƅP'e͜9aJE5rB3DkLHr(Pѡ.N}FME.PmPJ(l^mb3E?{, Й`6QK1;g^qp?ܵn9יYDH0+6#gٷyX.<}hƵr\{}S5 W'ߩ(lT=V:HߓBLI"H_TmQIy+zRFB)t[0 %ϽAO}4Tj{}*(Z]5mqL$iSHIKt|+ I3pTU  +C?fIjJ;<-ڌ1[:#*Wxn䬘#!/L x$-6c~UǓY쓇DԪY/HKxm 9Fu=\,42t,z*{RҖR {R(Q:G EQ\8u$C%P)FR-~) Cr%2(4(l3(4}% /K%;+UoڻWA(o`p L 5Q+I(d:h3m: rG9}>1k婪ciQ^`.}ռ2W3eb$7c2;#:fE{wN[k<؜'dp>4Zhb&?7fRnDO?h|+k5 -Qlܡ3Ho脚E^(% VR%K⠽*"e&PB$+^Q2 hR%4HB !uڈ>2 vSQ#hfoD1nt8 `6um{O## ze%kNm]}3絉kWX< i.܉{yQf"W推?|Kg:Kmt _W )P$I$͟ʹQ?0)cd m½1lsYQrb=RrXV"jXamXS;ÕIWCPcR0߀믕'a:Fn8QJxqƝwjk+׶@i`JS)R=)d{\Րʊ #-A"GA]SA>%-wb5E5- ;dl7+vu+pL-Fk`;-hv+/g@(^wՀTQ<x&55UU /!M@Dp~o^R8r{ PcEp$啒b%Ex$9^ ~N,]~Bj$&k"Tn\K/u՝BpJ`N -BN'F`i"B6Z zSZ9!ee A񻺋xt7YF.TZ?R/7(5+Ytܢk<N *QdwzE`Vb,9%l_ʛCӔ""K*ޠZda='|$nH/eB(BAw#N#YRuP:S՝nW.#Tojl(?zۣѹuaXh]X謍.OG}]!s~%1GؓT(2,;\+kGMcvi{h:g dѵdaujmͺ4U٦JZ2,$=d'?m8>6f-f '\mhSN2U-hj EpRݨy-cTk]!iy~ÚQoߣm. МMﴧLu*3 ߇o'.f+1k5![R9.w QOlXPxI)hܥ0"9xS[+~O\ 6iX{bRhX3 #4D&2T*>3kJ^ M2t3CTŪTvkaذx<64/t8xNh1kHl;9ePY'[GX%IW{`T1&Jc+Z9ܠ\iA \n:HIn ՁjO.1&`[L>3VܡU|PWVYLWLͶ'MӮoub,0ػ:-Dwb?lD0懋Y !hmB=-g|&WLӨdiU/d?D9 ~3|Ot]^kY+>G|L{XQJ?z@}GD"3br x"p4,SNN'}𞑂!PO32bg^H!x+H('[Vka(EX4;;:{Vr`eD-Z4JTnV4=#bSE+fD]M|*-24YNC.מ7oV^x ¯ȟ؀KelJe'ۜ+Uɵ{ל8?_9z'8SMs2TM1K9L0TsָjRSuhskUmqޒݛz=UW;ww|u/?SxclrnsH.sq|)'ORBV2`$/ R;,qv9BF֔ӑJ:8 }w].Q BT,. .OK;j\ ^4&aRL5pzPidL+`y9`iQ ݽ0G~.beR')ZuPuN)sd'9)k]aa0bj&u1/0fDZRxjFn54O=k|$gHKrDjf>7"LY=+^Uv^8{6'/!6by׌[1&򔚭K P%4 J 2!+kl6aBlT6aZ-ՌyS,2"@&`8jЊw*J1'+MRA|"Q(Xe%>ptPo ƅ4@Se\s SXQ;2FTg&Yhy>_Lc6QvQD{̍!0쭣ōGvՁJFsn# VW@mN64RTP;Bķ )dSQY Eia%øIUaPTmaǜyܢV4_qy~^'D:V oV}18v6$C#2tp̄awcMD.!%QPo1KӌŮ7|j졳QKԠ3U vV` jvjF_] `@V.&WPa.&IRK&e$Ƣ ܺWs7z˝W|-WC2v|'n_?aӞ3nex$w3 J(K9^sU«&Yysgxg=^ZyWLG"uaTXgeOeRow=ܞ8~5_y*  A@M @yYI14%DB!,nۈ-Sn*aTʾJPʓLe9V$V!V$ W4쬨J4]u7UԸt&ZґBJ+JsRGK4{8 /O(4 À~J>unc1 6ٿyQGə`_Wudɽon!sFbVZu4hiRЋJn- Eр\ڄ[U`7P[W[6]f2s/%'` !|]!z&l[J2!>Cq9NQޯ' MNvФFBxY DQN#3EBۂD1B5dU[ytQ .P(jѯCS8FX@mV/([3(s{{s/>[mںMۂo[wxw^}k6M1][xpaȹ(4)׋m~Q H܃ 7@$N3I!G VBpx UYneAU-MΌ<,lx`pR0+Z  )LLjHZ,v֞ej3ۂBAm!h)mSmnv=Iv{J$^' z,uсֵw'4Zrb(PŨJ9WTBHE(U>(*i i% ¸bc#9`xɪM9$֥D#I\m]IŠ@AE'\}a>[۞I>T?GbgG-^ /=tS|`[})H4>ql4VqC?f9d2SH 2qT%)Dmڡnqqq3***jcߙLmnno2lܔIf}ZהK2%5t Ҋ<4)Wʗ5˦igg3Jg$JO W18EƲ/~!YL3L8`z1eɦ#}HZU*R&+߄U*S`gXT*(d',ҏ뒉X$u `n_cjiTjf* ]iu剘Fh(- I|!ɯz\v7]_,Oм+ Nc2֥SFElpOaG :>2A8: `Ff/ٜų5a/ݮU$n=bÏrxҩX;4%6G7,H5~qE_}]qr,<*[%}BRjH;{={<*K|v?C*gh,9![8dl۵x݂ZA:jjAݟQ4+Oc$e-Avv y>Xm 1$Nt7H:xSݡIy,R70N- ]DJJFZ/OMO@NP҈MTYW')4lZQliWH+=X#pgjW/u*ŦټтWZE_=fcWq``~wD:7(a5pF/_fH,6*hJ+V# Fhl 2'>.2ձ(؛K>nI.MtOfZU2i[~3M]w |c?yeHM{`׻':l !69/b~Zc0D}Up&XX8p *ufQvA[+0]2]S.YTMPs3sqy'}ps?揪''TOsoUZMͲtH *JUp6'K-h3s)E \/UŅ-nRRtRIn/2Hm/3v\% 4.K4m[+[=h=F'>?$*> TY#x pA?BDū9㳔]oS6b볝q[ccmYဴ],>]gO#g1|yClJ?O,|DOj 馰8uF\lX':p;l-ƺط~wfj3 q#5X$DׄC+qMKU ,?E"p0U%5Zy6 1V㡥Q 䏦:Hx)5蠬Q RzNШUMS NKVEAيV*Du۪~\GP▸SUuLj?FլƷZ6MݚV_Z]^Y^ͮWVkhֻx6xM.z7'7TݥOcˏwxߓ;GxRI'KOThSJ}'|=_]`Ԓ-jvgo vjD4'ǛlgfӢjfiV4ly2oJU)AajMẑJB]L$A^͊G.W{Z UKO,Xv|zz.:=#ޝ^5 Nz 9GpZ)JΊԭdnAP$zvkP KFmx4p3g$8Q}A^{ .\w^d{Ϧ \d/smRv1q[.u<,jg76DyCsϫv/OFjAS % D @"dG6":Z^4RMjW ۫:I2ԒʧaV;->7K6`@GAhIip͘E, QѰmtt몴%D%z%CsT_y< r3i85s=t>HdlIm" Dl,Yjo@VR>ॏB"iѝן(LCq2ۢb7; qf&kYԘdF+%JJCڍF6qL^^@UR#TC$QV潗T5={ vuYYK")EbΠ+`JOVLGZPe/7~~ wN̿7:LJ˹?M_z|ij4$m1rӝ)'Zɿ~#4=0B0x-rI.,m80eϏk 3.jY)][<MM9>GJ.K%V ovq(i\HDTZDetpEx}KKؕ8T#;;##//sKB?Vy*pt!@T1 q /8<Ri8K{bZ(B*F$JH$F㮛sRPLlP '^Na/e9UJ)Pj$5Rqu.i̸;;Jݔ`%;w&;Sy6':LL?E4  lB#'LTd }:PW_wM &/MM:K˜InAr. P+ԦvׅVu 4D"_5~B0S鋟 I(wܮl=|ahY4?euV,~nͰ0Ks0x<*~ωfUΦաMAtd"%(J^4l6Qύ4:Qut[,Q^O =1@=zKz^KuN39YdɄf/:g X# hFTF;Gk/ݾŕ jWn[*֗L_ko UEh<' $aDL)*#'k/L?kFQ;SVw^〤iӱTG4+%BUw^PUbQ,O/ӿ t>\>Y;Pᰁ7PhNHR"i5IWAs)jc1RX#Q-wXKJqh7il3 6yCŖj(]\W0^"}$MMk5x_T78PԢ&6h5I,0'd.VR2ƪx ш3 "ٹ5-n,bDM.DH-lKE`g{n)&+TjRB!b8!}rxOY;HUcЮ-6TCz"Ȥa)]..5.-/o߹t:; wwݷHuS׷֮B& /&bnƊ͉u% 8M̢LS'3J&/z{9.^{]"o"Ŧ1&4ߟ -f:]5-kI$ ID#фFIKp# Pn> 6RqkpXiKEzzN`;T,JShP+:Vhot@irguֲ:*e8ʛ(ЅɚG^\imΠ. 7p"[$v5b҆m%H:2-A)H- pu BtM؈ ; nU;z&x2ZNX*y(C2Fdc!7VDiEE fl 𞉺dԉYՏVp.rײi d n'ms7}(ћVUILz霠]X%k蚦Nk;Vq7-em5 Bsk~h&rI>):>>W0H܅w.Oj%n?Sa-a Gi"^f5  XG ˛ gpes*(t@`n6_Q}%NXJvBz-]5X$Cpރd:</y8COaɔLJ?ӵVIR~EwBP69Is@0uXzg;x=& 3-i 6GkyLn@qI2̣fybi$'ĝS]es;kk*[DͬU¼ɼQH|X~$>YD. \xt<[1a]K5*H%Zl6DsٗzWZeoB+4|h_ M<p\0 G^Cg:wjCQlE48ɭO M 5g&O]Vï1rAj**ja}`}PV{vD}F~VkhZX?xw81Qۨa1m}7gS[f_g'r<;l2׈ !(Et$ʑPtt߹9zMU+~ߝ0!̜{^qDW8SQbd#=(0#ztOԤ(I:7?}R&5};v*NNd6U-]!E06:::hsv?/4ϝpTT7gRT8[IKsݝO&Ceeow?M9a170/VzߥW_C=buS$/~ve-skЕ,^1nDre6%IܷuƋwqk\3eC1X5'Ixu *B5.1&xZ^nly58J?ą"FfX̭A-tb,kV8rxU%VnNW,0v:7\EJ_*,$)^8xqk%Bk6mڏiF'R)rntehWg?+K*Z5. sYN}paRJF.*11|1wLc+rwáͨɹXEr41FM22vW{Gݜ^*ӅVZ\/_!뙜F(C axe@ÐD(ɬFJ$d5pH 6jsr}5@G 4IDmq"nTIG+p,kowJ֨;7N+躶/xdk}{ߣ{;*y勋З UV^4a[!N`:w3 baQm=W!ntaKL(6V%H\ˡq[` /; çp\X6JCWW&#:cDsdA_,s5 '{7 0IG P۹L39tD<| AT' "K gZLTD|lefL7ly.n1lv%I&t`w#~|[V[nq5~XxVߪ8rN+HxLddQ%C̞nkv;aiu"㉰k:NG:L49!MTOOJ*Y@@yO %;;M4Ս c1/؎ ԦMY.?@q^Dbsa.l'<4 "p1c(ˏw{(m̎SI13nIZiX+;;ոZUxw0:j,C =xfle$jMLO55UX'RNw2J& I9A>@`f0Ѽ"Vn TzHE&歚z%w'wn[,D%&bᑆ\<^p5wŒڳ .Got8}%{h"_>,%){?'yi#wSM8Ҩ+.GTWnlߓڈ~*o=TؼZ~x>?X>6ˮll~M n-,@|/gp8H%J ^LUXK壵{X D]F/e d-YRzHЬ>?7)&2製{!]pI e[| ]×TC_"}-pHʕ?w3hKNȬV@Z)3v{tez(=>֤-X2]C⏊FzQx\o M->.bEMZCgLYܳ*6^).{Pzje1QS+6>MoN| NK'Xb2;|VTWfUG;4Y# S#J~ KX 8QI4"ī GԦ#.:Mwu `du'W& rL.UV7$gWtwQI ҵB(CV4-e6/M+H/-^$2dg~PlZhkd.Oq;iSĂ0Zq:fYsd˅QVb59Jc3>U_ lO6:㊓I>+N;Y `q.-~2oˍ5[e Z{W\ebs_oi}}>hu_ p&+N,hxoV[D9smܡm u(8p%&2B(zxe&^Vx^ 72hk9Qĭ:y/֑3̅[Lm1HXQf)a"Z;4iEӠ2eHiPU,4|5*2U:|t*,p}dቩVDF~EFrEFŚe_ގveQeQxs @$} 5͈v-}.x UCfPW^PbG?ք591ڡ91qhoGf)T{3a8oUl L8Āeh&-J!VN[TNVl "="R8$?5""DDH7ߟkFyH&~u$s6lnRFVKA/H_!yi˘zѠ.֦گUi5W-pkUC5 ~ҡ"y.Y# JM/sUMw΍9ֈUPީo]JoA\"]J|bUH<;sUe.80^Ϝ$q ! e([PuxyP M X* ,m0{9^nՇKO&Bij2:da0nP8Y&c^H0$gfq`#s|Z[M(v]u>9 8Rxx0sf6Ł<xlPeLh+)Pi|(>??8!j/q,bq,k0gv)_.0LQx ! &aG PaSٌbL&*يuzi{s^h͜ps!@z'U6(/КL?vngອmfL9]s>kꞞ?0a0mNxqttJ^[@w?}[2S5LoL;<Q4K:8TU[l3HnĿ["xo]&kJ+Kg܁H8y5wKkA3by$t8d$Ks&ܝ tk~C/ gL{ZDI'[\^t5ZY\ Y_X[7c<U39e!Q?x1QlqcmA5#g /tժ:ҎN3ހj{kس͂T'J [к|?̚rrٮ, 7oQo}~ˍٮikpX,K$e5FAY?c|쨚ՠɌ0#cP %2 mBX]'cLC7W+B)VP@;lywA&)z4{ǐ$e>{Ig2eoNLfoul[lNLL\sgSԗWJu G?Ŋ$mmlm9“n77?U[[t"밸Ǫ/rJ^.51i]g}]]j[;⿊Z-EBBh:~SDt5U jjg ‘U\BePM%^Ln3QӇ`t:_dG8pϑqfePt\mkC5`"a^* gԢ_ 7+`#uu1CGKGE QYZ)A`_wpT$ dH/!/meƊG#FU jO*tjPlCm9 8\RL뻔5_|cIM{/͛ W.,Vw5ڨݝ/.L'\a/CѢEǩiN^_28`f.-+d,IGa ʰ5!]=3LuFʄ'f¥q|<֝ /2/&ӽ:f>ޣT2i=׮șDhŋJ^8Pd:$ hYg xGi1ݳ;bEHӿ~8wPq:p'cKg[Σt~VFF6dFnK q՜%hZ l}כ1zm`5jt่GfYr{;`_ײ6׵._36mssQH-߰\VThne[yU״|zNxݔ:ܛd[/_yMke7)f*(%r&]P}uE[ YC\"Ol"p3pYMKCPX(3T(0lŦnD'!VQU0-[1ϙ:Q4xwdH|lm8ajwS qkYTbQ*ega Q*."ngz&f hR~3w3C 7r1.+b!v1^jF dʭ βX֗ʽPyk#pv;R>S掔i?dLޝ [U\&/kg–eP&SpMRiAĚ[c1"zqaTOU?Tѣ.i #L?zɌfdx2se!oUpٿ] gx&=Ay@V+c2/-t?|.PZDMw7-8H]M]1ݛu%yΏN!k.HmO8g 0#cTNBh_c/bBq`xz *mTTE# ^r~9089M$i'I&l2!p5"؅{S_tB:םㆃ_\0#}?DR}5vyFdz~͐fTsDӼsU93h% #Uˏ^v'"_Y& H&DC|Y@6\FC%%I1KڬN_nfI.G&>-g  ,@^nojŽǻ'PlN T6Ҩ>Y[6‘3ᦟ }t-?WƇn{aW{+ek)RjìFpZgF>"8Qޕg,re>k,:VGBҶA'0-0,L(@'`X&}< {N >,"L2c5Q cp`8!4&CΒ"g5f+Xe?,AhHKAYۘv}n~moW7i0oкU̡E=Xjp{Tte*Lpl6-lkin"/c, Hjwq/gBծ!jb=3Xނ;t[˂YhMDYhi CL}[DA>na´gMhUKjGŇV~ʝw=-,})K jܸj`eW*K8_~iw8~5?U-atjlPZO?6\5'RkN/kO2Tt1G.5iڂR Ѭoc|UAF*<+YX«l 72Xh&BFA^+4ϘnٛsJ~$ἦ/EٕW+d[{½+7eWGovwFg"Ÿ~ GF[Ђ_f̾m҇s|9V9h2t&Cp3_+yAg H$bA+\?SduqϹ~w1\݊}Me-LĞN!<뾭$ev!4Dcʺwwd48{QQ$omM"Q+mY69^z?Rw+/s%;׬o&4!To}D V>YldXRR=My#&ϖ~#u6RI#D F R}$eej0?ŧ҂:R$ȸ/.1. 8TAK1)W*#@D3)fy7EA\UG5H759&3Kd8FS;36<@*ܤ FHlH$"yT,8!rA7|vp͍d̚|Hn%^<3SQص}Ik ҩS}U[U[1|9n/(J.mxLW$>׊3-C-#-:k80dTTc/{]z9C wU *ѓL{1}w;Awȗ 7/>(/ngܲʖM-dney$x׃)L4BlQla[7{6GTsx/6٨X BT}>/.pر܏(Ohs;d?dqڦR~_!XŐK=NPgT-Sh:T?G}gS؊ԙ tn5pݦ&㪡ms='A?]iZiddW)/vy}~8LyWZqTg*c?uʸgr2B1t$ą6uEG3:GAm}h"yWNUY 0L)wϬZ\1[ϕD+6w鲗^jIGRlߕd4ߞESa^&}M[mK[U^p?M\W#kQNjIgU l^8{]yfBdO73.OHdђ\e߬ifqRuk')3ؓu@ҎsyX^>=tq*:$&5ݾ9ΰ00>_IQ=N)s؁q":@6TxB|QԊ bIOwǏdbZA:%h.cL  0NH tA ( 5'e utq=x;9FDzosN99 A_o(U@^{ bC܈&z"e`T Ԭ ҨP(T7J!Sǃ/yƆVmuƂdO[3DRu#d1X^ym[Q2UYq/9tm$aˡB I^NDtVzZ,ꪽ$PV2 v2^=z IhIЄqOj\>-kijaav$X-S d)0Tx#Fi8(r/"B!3"TЈP2$xkI1oO$+hT8(Փ-H#O$Nߝ)< } 'N&N+x!/g :cH)CZ){Km˅3}cw'N< wy$yaY٦Q3B’eɅU_8 ]Јp>E&^x&dTIopP|pb">$c>ao0 7EՆgtP@  S3z zbM+x/<%[T^[;xJ$I\0MXܔJro7KO@K%$MGpRpkԪ:J9dd&2g2B??9M̲?9u Y~Ȁ޳~`0Է6RfIU֚wVS:B}.E4lmq!I܈\@L}xf"'Fz* \ Em*`cUQG%sULb#@O}՛rwKNo;S]IIL2EFrSNqcA_k)tM&;\"aSOs͇*!\MIۚ TVDyu#ɇm*)U/SѯzZ<`_(CCC/_2ƸiXc|YvWi UmU:tԹԸRZi[^\^ުtMvKm=Ƥ1׼$UڬEr1)vRmu8{oHdWԐC U J5&#ӗ0:=nw,M/n/K[[ !wFme`Mݦ>_o;1_PɤZziY>Ar9arRk0yZR 􊼩U([4/Q,g"n!e.h4C ']HS1G}YMRY;`Rd3\i!hpЖgo zEOTݛG ־IjW_b<'1f^{e_t,h׮r$v*&e:`:))"=1(u3F#*~Pҿݐ\(Y H182KUs:FmT'#gV k%![EU& ,uI lxQT!`H6^$k!p% n5#1tpUJd nÄܕb4c'{ 4WMȬ !&}5FpXoofyloG^'@DcFw% IoZ%޼ϡu߂|~@Xv\@MAYj-~Wak{xixNhx\ |m"CδV$56>ds5&?}~QtB\6l#7hD}bpXgN&-T1V Y[=9!*i!O"/ÍD7x>=.e_1mbrGф9۷>0U3:m*\B?zwJی{@ӝC8rݬ (϶S㱉~ݕG_=m YژH{ {lΊRËOY>P N7ӿfv ,7jλ[yƸcB$M~]Qhk1͘yf\#yٳK[{]|@8Wi.9cjp[9ִ\K?~--t tnZ9kIu %;\ܭ".yK]aTpŕf6j,Vk8y^9,3>Eӫڒ٤6YD9 7XxZ*iɬ̼_T=+=T0 G9E\z~gyYB;+]Oj{4BoLѣa3΋iaί@Ud=AJƣe6nD$K9.w( 21D#)$: 33t1d8WTG2|Yk wu)0FЎ@6??LPFnX(|Cax&~QoYZc{cWԞroqsJ-:>z{<79}Xz{gR}muGTz{6mh~o)|Z~&yQĢzHAo3bƭh2ܙ=\La`Nl͕^3dyAEmZ2f7Tы]sr$Eܸ6>oF?ss/zOniMb2={k*Hs7dSej ]`rxMl뷡fm] >Z$'̊RiD<#6>S} ]Ca嶋;wǦڄh~lbc6疓`rDh#!ZiM֮;I }=;>.N ^HI}U"3W r 27?],g.'#!4|Rs;IUA8!aCX6A#:,]K ,tLQD!y-|4Beu(ʭv>΍'Hb+GjMC. c臥~E2+!=U.l sol6AX'ss,ԙaEAi2I?־| 'ɷ٥.r7_vpG4jG5~_k~)5K)[CWt1yN}Ӂ\pYK"^yW$/llo bk i H]][f%/0-\tK_[޼⇗{ٲ[o57mϯ )k TjiմfVմڇjZC5VPM}iqVmoiVei>hѫr@ڮwsVy֣O{VVfKfJY,,gaLg_?YYyCћզBgC{v[o΅2m>7j3Ff6N`S3o0^V*埃pY`m3翆T=W4ikk±vB؈Viu"0gpm& Ԭ<7F., coɫ4D RUCA{a qMgOⅣ`')\ǿz`W~uKj5q1j pX| 0RJ"0 9# cdsm?8j5C"vOO֮ OC}%8Rv~;{7C|Cw;o|tt>}sp&[mj< en^)yPFAC~#ppQ1:_4 XEi>[&;wbskrԎUpĆ%! 쬪JJ41 U]И] [Z|т:ma0ۄ4i0Z6V6P&L{{g}G HɶÒDؖr픈NU;U}nZE$$|H6yjf%1ZXY*e[nIR#2◻A'봯qw>w6}Z.sn9.yYʹDZ\\MUuMm~qwvs&KόGyxI%NfӀ 8P~ck*| J>:oQB ^/#4u6[msJ J J TץOC8d$~>}7XO#^"~[h ^Wz\'=I =aϫy-ߑ_MtmDF:Flq5; n[^1i-W׆ a_aEzb†5n߳|*MV8y<'@& āi& +dv'^0kĸ^Ke,w$1CndPV3:2pc07o 1f;&‹!23*`8$VX娡lƍ:/ᓚ1 >%8.hR)R3lŌԁ,@p$ e$t&9"A3གqHR> )oc! !^o]EZ/Ù!xHÔ0SPY_fGI/q_MwD,=oK/K? 󉥟aWTѻV-@Nm|a?d 6QES ~A7Q $#AQ'VtY߲@7ITd+z VE9K?$${2E"z嵒Ngt979׻.jr\%Ո;7,gIb$꒰Oi)=OM}tyo=6]/g+~/)}FɁ,(wl5ًrr4m^$鉠ywѴo̴x ߵP>" hv@[n 6vV0y?X3^ј6qQE j\R h}"0j&h4'PPQ`44 sĴ:~djJMP0_{+D0X9|0E):4`e|1IW2:LSIkO\u<~$שʏiӏ yxJ\ikXi:H?Uӄo;PK6-O$g6PW+C;yno#xug}N'H|,R<[ ,vhܽo,kꦞ2B2'.4)5[ӯҴ^y}UJ9kka)sje/|oaDg1"g O^-DEJl"L&nyyP^`_|l3;@{.+x!3"c՞gbkGvtnS{VOV)oJ.  `crL4^j\"]$EeYqWl1!E[@]H%U y'WC endstream endobj 512 0 obj <> stream xګ c endstream endobj 513 0 obj <> stream x|y|Ty7O2fLYl@@ @ @ kh]JHjW[bO~Jf~7 ~~~{ng !%ډhT40+ ,_y'?y)B8!UWNjN݉(BVۺ/XsB)ۚ(T?K@n[Y?pn ҟ#DzڑAw]QZNgq s}j![gck,-(M;$I(B<ޏVQ,( -a$ry)+U2_ReKnKO փO7If# f9!Л {>$!= ^|5Հ7O=nJ]Q=^Eh.:'hb A<G܅RH݆Wdq#D{ѵh 9Z^FRtN ?*C?F2QKTnB{3F,D_f~I藸 ;%R ]nV(c=NS:1B-Ԏ(O jEzi!!HjZ\BE3' $D5FM- \ d9uX-؋_vt3 VK(t&63y jB? h{;f:NM~sq+ǯM$nƒ X5hځoBEBg2ߥ_!52Z֕h }0NsJCiu5Acz}=L}! yہw3E?DDs@ɵf|LϘ_J><9Z P\ cـN^CA@N\ wwgMo! fZ͒wsٮ20;#,nx8E/a~\+Z|;ޏߦfRk>j#\G݌9dt0ݑ)@Dn 0p-Cmp t8 +iڏ@?E_@oY؃Cx)kv>L(nI=BߤLFjt|J*/ֱ+'d?oӪ9JoH,\"pәÙӂ _\!Tӌf0&At\OFQHOOo;p}>Iӧ<Ɇ}/+*o~<_ħM K.\)e RA͡Q+j#u?8,u>p/4hgҝRVZaY-g/ρ6 SfgޕNݒ}p}WH$av&>ДN)'qZ .5̌Q܁шgb -j z|+jhzM>@ 73~Xo^i$ d~1l 7ӠCM$=m@n* 6 CT-ڊ9-BһdGy: 0:@Mf^ֽE `@<B^ޤc?rhz[0C%z*1WQ+zԁe{^f>>@38};[(Pzџ%V,JA WPU~o8b :OsTn2c( VG T&s'? لμD3]̬/}:ew% 3Mo\OUUih+U+Fy,!(ee j.ʥ>+~I;j$J`o]AX5[-G/_ kZ <QK0~pH_^V<rIK`[k|3hLY`/ykiUed"^\TXE¡`z8+7۬hJX)b˹!&93}]5%cY/ hŘ<`&/bXU^kqx܅E`5Tmk!k~ Wߣȏ# %JG em8B!554} dCt{uӑ+}+nHPP͐~zlܑ[FuhݵdAG߆!3 IhPpR'=hHrpp7©r6.|p:t} !BO"NHr:ߚˁ!4ogOdEFn}3Tut51y[G[>Sw(n>N<6͜94\J#>{n[, )L/8⇲'%\j28B$} Ed_w%`e~ F)q~NhkNʹ)tw=O8?3y6_:-њMv:;5N"hr\+7 YZBant&EuIrON&chn t.J bTF5(kA_uҧXg)d1󔓷ڒgsg$wܙ0oq$ͧ\9} ݫ;Ic~'xJ5;Io>^&[ex3@hTW46K Ϝ@ݝ#AmB|<ҼsHbhLag iQw(?Hf՘nl *ٮ{ɆtcXw`c_ %"JtUU^q@\Qg'AJYAꬖ)-.#)J=Z( {߱{[,psv}ÕSg`/q sR-f?-zZBض1mEtMa L P*CNz:2' ) dޓ@"x5Z aS"85fP[Gmv嶣6zURH QP\Eř0v&Lf c`2bd4~,9T*͑r1/l0-:\hy/ͩ1q{ ohiobLtK+-B, rDBbHXXvXnH,ɍVhS@#G^$'*H3Q(N d\$I@L%+]ſR bNIhGq X7Tad bX a`jƏ>'9CV⣪OOOx"@ꌘrXXmڱ$5{ |m# ύ]Cʧ?f^G0Nv)efxv?8w=QH8Pt")ET,VU!u ,ve>K$l|'/[Go)*`G ;-B>"X-wNQzA- Mx糠twPn#:EA[>6rfuPu}K>j@hXaM#X 0ry¦"vno!˓Mͅӹv\ti21 o][H-U/,ծUi}ګt;w<~PVFyd~{jOwղ4{d7ݔ>}'ӪÚC *<_P=yQ7Rp\R0W٪jS/o/JMV,L, RmaùW;Nh9dD2亨Aq+**ouܞw=Gd؝INo(YǴ!_2ڍ+wcRqz+")t*\rd`ZOE[#:$6\7nD#f?D&1 E8D DV,>/ACDY"lo~+s z,W!srk\׆ xk՚k*sކtUkhWq*mw{xוּDazpѼAYa\zëX}5WFAu9xTcY[rU|njBKttb[a@P, K]{x)~8)e}8H|ﭗ%a㒼mLȬ3;vS{QP.0 %`(-/l./Ds< 5!FBl˦>1fa BlGEDsM(>0@uVnz>l)^zH_0PP^[P/T-|BӁ:,9V@tJY6r-(a ;߳ Jmz﬎F-7̙ݴŻ66>?sվ=:\ضf}4R|x}km;??j~zxWÜ-!~-vbRɩ&HJ(qِQǰbSck #ȵZ]ê8J:֨uQZ^og_g)7+lρYu8%DA!"ݫU?~CVcUPR#YX#΀h"\L/݄OǢpta%.!ߏXT}/#YYj~Ɇ[Fu>\YH߼s8(m{֝Ngxcjv l^,YFX@XOHS&PAU Iu:| ugO {įs `GB=E"\Y1/|8LCj~3Gs 6+ƈSWox<F{H *Tר稗ڭԎ)S_:$=-}C*#ȦhG$;ԏFxl")9ܠ).)d&mTS"'&Rڹow{n^.qG cnjy-,-w݋'UǼa7)[uEK?(_VwX6y%, J* 7-J*xTҩp({wUJks̅jފdIT9`Wn|>8U=Iib) 4 'e2}`иNtp/ L򢠳gDhTHAL9|4aWy9Y6Fi :ؼaH(TݳF^Pz^A)܋:#epIXK@4N' ɃՕDVNW*EMg?FLjt[36U=AKJ #LPTq5'':GqNE%(d3 =d^6x[31WWkZ]rIpUsdM9g_>[W/mX]Pk`/v~,,aYgK_hK]tP/`L' mr*, +]3&Y|bR]̷nj.D>-{s52/s2L.q"̡A'/STB't*}~+ )\xl&U, hxhhkl;pψn&<ѱ,u,0zE,$IzbqG&nqB_R{VVe-s5fxyw~s[Zҧ6ΫJzo{:Wio/.{zAe"}ƼӯU' Y_CGkZWC#$}$aFPFAK6Bt^a(H;͟t{~Ռ!_0CUx9 i7U2Ajb)I5wC8֕T1JQuEFݠ::.P cLX=9]/yiDcRϲ&Ptx\5_ezxȭ7N[h/ |W*=7{JUOrA4ܹiV%K܉3`ֱrct,f3hJc%9{Irx}9TnN;k0WXV.aK.Xʺ|_߮+iXE8ݑ+LMC/aA#O2:W6ommPTպggiճj-X>(1v.|9Ᏹ~֠7ͤ Yڣbt"GTuڊ@E`KEhj.߈ȉ&MeĺH7F,Hsc1rkK9`U*39;_+f¦t9gA4h}vDQVdQpɛy#/Br.⼤|o/uZREζɧ DBwk@MlqE!FĖKxgUTޭz)7a۝M0Kn;†uuKӝe:v105,y_Oo{jGXJg| 3R R!놊!RQLv݇-HgQ8\iQQޡb**u<&T:h7ҪQHoљtm53RŁ|zC%G"&?n&1H5x6ͩK) MiWC7ӱ֚t+ ؃|:5qTpĄUD B*iXU2|:&<5$kd 9M1 6L6X!=L(҇˭k*FYJ87&M64A`Đ-;AǪ' FDMHTF ^GȫFtjG5'GMg/Ѕ 08Q|j8f${! J$+U֠HEɈU#Ma83g]Dմ{jb!X}armЈڢL=ӽtU]依XhC|*<Q+T={:a4KO5+}TAy}[`JFޚ(ʳ;~Α|8,fr"dB3y8\w_~e78O< #,9nޑjG9g2 NY䕭JFh^)m*ͥ`0kWl]@\8OA~^E ȀO0PQ\+\rR\1‰ ,q{H"}f@.90:Xgki ek,̹; 'p؉7 + 7 +_yv_xs]vrײT0a'ä5# 7I#}`f/|%job2%eK[c쵬mUml]Y9vs՞5~+W>Suce+ \Vtm=u4̛G)F|[ɖ.H4%o[t{x^Q[ RWV9Ylˈ5H(q]YmF3QLwS9l9BiͣI=n "&fR$BK [Fɼ䭅d_&VZ ”=,c΍uSIIB2x1q<{E5˓1l> `ATA@^U,K Z,gmbd^q< ` S?!S ߤ]n 3N,K!uN[(Uxιs * rBa/{;}nVyWi`E T=/ v+}Wq|xN_PSWQjF`-"_7pmhk41չtB4sjwQnD 4N ]@Zr2syyV|UG'A$"q%ysS날9Q^pPca0rN1$bXt͏}K8$^'N 1P*t97˜N|6c s82v̹?[_a.QLN46 ?YK8)w i/xK⵹:JqwUbØ8s\A)T9եӋt:oP~h 9dǨMV%# 3jdGO2JNKglÆa 6b[F-mc}~l*T*_(MlnK;SX;4$;$k#_B|+E~SxIYSf|*YdM\.¡ZJ Ⱦ<vpϼo˛nzwW|zfz7Ə>@ƕECq7ǷT=zN-)77y=-C"'^qh꽭h.BI/h5dqX,fkt'xM[kA~\Y8J{4niЯPB-;aC; n> "]bdG($DK;5Exr n! _a 'g)""O-%%C5}߸`G5o)jX-tDYj׽YL`[7&]nIg[-n} ׵.64nUѿՕ?\LӀwua.O//Űisotud^r5zL8MaOG>k H c@r9<[p"9/o`_~X9>9-!x! 9Ia^rN cQsYE ܅eKd %k &V1@On ~J$d];8|܄'[= ʔz#֕ʓr&[v @]Umd~umk *\|Wl l?г?Ȕ֦4k+Bҧ q 5^Q2*b%k?0i~fUJjK W4oprpvi*{mL"or]]|7nd>%j@IuvNκΌNAgY-?,gLX}Pٗ>ȊOaZ@)O0sǐo L HW$nh.,ݴSUrkWUoMu$C @Õ̵ȅ'M`%,Daڟ[kh-Q;@(h1#aYrbGN&3X0]h?F%lnnqդ41CY$ƈ#Ue%Ӗ7,Eq}+E>pdB-,de܉tgLgߝx76^`ab#A ǒ*{E &XW>PK?p(GGlm%ce(6ܹ6IgZm4X-C+B/V{d ʐ*Q^ֲռr}|~A{Z9lnGt 2Sp:(,ʪ*\ WX 9$Y)V!)id4V4JqLUFbP&i#FfOysmc\fݸ(1'_ ^Svi݈,Ʊv_8Y>MЩM8i<"'yCWh4G,wB<18N}r gj.bgG|_lcIPIŦX5UZJLHG\sJZ||RN0r7%ҐY{ds4~FA^g^e>O_|?N9Uzr@i0Prs|Fklq, |>qץ¼ &A-3o{HNeNEyL*,ҙ1nC@`yVۊ,ny)asSgmxNm#Pʔ . d>ƈ#PvM b%$úJZwZ4g-&ڧo,q[(עq=p/O\'_?d^&ebߐ&oUܢZnֺ.l0d|tyyEjyҺv'Ec诨 ]$^:TlM-uCmށ R*; h#ff@XRT,̢,,K&j>jJx0FZɥYBRɪ,L2XqV,-YXT[$faEGwk! u1P_b쩴- &\&H3\H |m 5G!p8?!8F0!0+Bn}:B '-Np]](); z@ѣ tH I204,h__DQa^}v­#HGÚ4Z!l.)n, '_Va^P;45p4Ws*Nd/ܿ'[{wpO8 z+^˩82Nkո!5&܋{.-4PGf{2 k NkdJ%B`1 Ǩ ~f8OAf*C.QtPH a:j~#@ ˇPn]ǗA${ h "$V r?=E$:a?2<:808!>7>S )^}qܯF@|X@|&(4rPR=wm끘y:Fh^*6F0!hNBȼ$H6gvOt-uW!]* \09Iw*>_~xB/`w^vl[^ÚdNd L&12Jd̻|T TG")C($42 BCFjn*6yCe!yG07^WpCFb!Qs{ ݣ/RF'WT0NwxkG\^c1T˧7|my>ef[-w涅Cr;v4h,Ghmͭ P]G16V r?6m$ΡFhǐW7ա[TW ;!)zv$]lQ~m~-)q&E"5l qAeCy!5t [co|flٲe-mC`}yCG0oRexysTnh_ y*n'??FI+Q $%Fuh&Nd>=bHm&КfZ) endstream endobj 515 0 obj <> stream xڅY \g2 4cg^xjUEQr$3bTp!7*QGk;jZu[moghpoy"0@GT͜Z -eo0NKa,-`ؿF'p^tr[/ G4FpLN 8$06sƆa$M / U+*HmTɓ\R'EGhS'O6?Δ{D4ё eS)U%pW#cUJy""(&L +uEFҩ5<y*.ZS(4PNk#%ZRO(k yV5iV ƍLL⟛e S mPdk;Um Fbcq6&aS4Ml:6fcsy6[-cK7Va0l یbAX0"H,`JLX,`ZLcIB g6ۆ Yـ IZx!ԡW4KMt/$GMcy]Ry-Lű(_F>OJo2{)b^dc/I421IO, ֙\Ak^c&l){MmgO̾B^ԧANh?-zxPunuK!lt Hpݲp3͙L0$xdYȦBz6%+#(X"([猪1xbj- |\iaS_i/]&<i>qClo$xt4ƣ3"/GNKYYg-r9oy;;v諾 &1vM/3Mw{L-Ll6g6Sf>Q0۟\j=nZ\4GSS]ֶFAJ CB4-EKazAtG^4 !桐 N_K)}fr"ŗ;|6ۘcLD5U͵7F3/"!!0 >8XI9%A| < _קkw/&BNrj4!!m <{y =[eSY#? x.a ǣ4hO\0ɇxy got)yW^s'P|LʅysXP\41Dj*L"^5c۽D\a=N<}5-k8 ڧSX'XÁHzo PF[SyVk3rh83@" #re,Fz.bvg?!45a&#f?3qbүT]~:ȯ磓oݸ.wيfQY+>O}wc?_oܺ!bv@(\O𭡌"l?SBgh4ޡ+1P L SN sRzM7dSOg29'QNjSԶJ*9׶y֊rUW1 -1Dm:.i*ﰸ(Ľi[3dl >{ ]H 0 O}ŻmGO_Y|3CVhؘ[:c˗5%&)f^"} s 6̀ֈgތJeħHXQz*/So=@q_nf[/씢hᑈt ]f |S޴w2"/% n|؆9%>77ҫRmX?F!-C> wp<^UE-3uM|D`y ^5\MfO}nbv&mֵnRQժȒriae:=%-6VTͦ˦>?wFZ3R :eSjӋv҂"JܞN>2_ۑޒDחV%2ɆF#4 0pݺޞSz_+ Y8fC=]NS `fX" qSrӣtA'5+)Ê3|NpFz FAeMSJEQ![`f /_>Xٲ"5@d#j"~Zg!&1lE۠Ri*UrF &v?7=lʊ|['}7OaTdђ[N19QEHEM9s~bat"FGn;'d38 ̈́D]u\h3*AQ V =Z3xpEQȠݿe|&`¸UXe F*p>+uh}NM@#EK}اv7o]+p:xOjT.Z5M"6vDghIh؋_а~߽K瞟{DámFWi[hijHjpV9xVkZ6kd>x o5Vpi6(.)Pݱmd|31 )c_8_ڀ3:8qN?G)H305m>N<@j2b4U&\Qo PLбڲ>J+m)uA2ľJKyh'rKNU𫄪O(+ 5\DeHD"p Sϟw ^TKZ&pa&*[MeKq$gfQ1B!;%]YBɶu Tߤʪ&ȴtnJ-;G`CH!13prJ>|1ֵK&P!В\7ӳ6Gsld djP.ވl!…BIb1aꎮq΋.?|U>eY yT(-@֖6iX arwa(q folc^ƹ<1O\`v7Rʆy⟧;N}$3k4BKاK}g{@ 1'&sl:XDUsJytMk>zh4~nCeAfb2G9%ҚmGg^ @`K;qB2p;}v] B98[ڑs =$|w||%N?~ qԖJufN-Twʼ8 V@kX6ɒŗSHBBͺHC*Ԧrj$99$Kh$uG}QY[!}d8E|*^2mҚ\ąfpiTP!{ &VHv-+5u|}^Hr9I- 5,$o̝T}&D Uk5?Hv|^Rw6Q.mee-gZf5>8hۭ&ד߀3*!@ ` ^}hRIge4ˈNmX$@8 ?} |ɩ[_^7a(qng 5Gs/[/ ӭWccǣz|Wof76}!%!;:ڐ$FaZ?1+q3G^z9e.nlbcK[m3^͗{{$]]Qc?G.!Gg~&\B:*(amSU[]FHՑSMo- Qz ܵoULkf~co]esZ}|Ԋk֬83[WF={>= uMשnÉlôSP/]-L5ipF7l w.gOլ^7JNf/uM̑άk{ld5r#LZ\˴M"lh/\r̯U ٝO[> FIԯ( װp60 wE6b5)dx.گ5AjVy3> k2K%i L,( {΃YG]{O[l SD+}%.i, O6P~Iϐhr :–-˳_l;`'M(ќqFoadqG$_E'yg42-tG( NO^*+c\bTU>tCdu=s>wDP[C9`;=LLTl/v AjE:{{n&Š Q-lhLuS/LC/\PhS,/XU~%#DgtPy m>xa- Dh-{/FGZ`]eoL$SǓZ.K4C'J5w4h !o q\S7U"E}wA0 F_ڵKhl%Ƽal;o] %x<ψSUN'G b177Xɩ!7 ?X &ls5ҩ endstream endobj 517 0 obj <> stream xk``0\'9=b endstream endobj 519 0 obj <> stream x}X XSg־!AF~7u*.XQP*. da(e}UvAڪU[[ նbGVVlmm?oB'o=;9=_=!\7ԯ{ݬԫB4|:֝}qB,"XZW{/uZc˯&+!vﺂ?cNSN;B@8.$xB`P0楤UP_"NK\Z?Y{yzΟ/xCbԉژhyH\C!T'r8y"*D!WGȃ;zBGj'*[JMd;LLoUoxa?ߏ+j? yd- L;Cc“UdBOu7L˧!! ivW;Vϴ!<~HVi өT28ߑxE%#-KLONK*)ϦA&ed$J1qg\df2N5c2GG qHm>k*ig f6}k4. K%]7ksĪ*yаL0&<ҁ]u葄BS!\I΃%]OKva 6`nAdhBM\~zuWp*=X4`!$tdQH~(w5kG=Ž]G> 3[l@/,tj:&Έ^ֆ<>Y7}ǻN9z$M@܃ٹx1kZ{vȰc){Dpz@rlC5S-[SiD2@ Ocg.4ՍM L> S$rfj o޻)`SX7IWgD4D0QQL /ȲNs컔L/ %7S㍣?_,g6͑ uHH }B3Jn_*d`-HMjsi_2cTYݎdv԰n`@ܵh.4NpGA+Ł~,벁8 'qG&%iĈQ% >eGDc쮡ͦ=[)Vp7C.v<AҢoPzAЂFkf38I9$lf[b*ۇW]*s/8 2S =dϤ̸?χ2cÉ BiXjU3h I`T4UCR7K\AźrEACVaYv>Z ˮ8I~+QzqU&Sr֑ru ^jt2M]Z͘$blFgJ>q$3g6t=hX+.9^⏰Ao&?SFf%F>qvٺ$DY:ʰ&OV^XCR?>uJz#‰x\ac6{S?; !"GUx>i*g38s˭r,O3)'##)m?dtHK0ڞSРx$G`֊mcWJz(d$baWvC\Eml*~N>9뻍v3js[YuPO[-hPmaFX$~ky@yXI]ۋwON;XƍW}GZP1*kO`Қe uUʹr|rEqRq[r=rzf!eK/ʹB?ZS7TMEܔ,,X+-Z}- "%~}o-SoC!͇Ϋq˫U'SM[CaEG =cN. f1 ٽ*'eeM?ܯ?RLGRmZYlJ2dQ޽L /- Ŭ/ӷI#"ՠC6=fY(2uȋW-2vf#~!INg |}E٩yL42_}EEU&X:a?|MX"vR>|4h.n(ch]V[MRG)RP@: r# x.G,09_vn`@8Z,Tɭݽ~m_[>|_zS,Nkv* uǫ[*r>oqwދ Mگc5HCiL?z=nS a+Js^TX'=Tb~.0w0YìG4T$$񽗞|q^R NӿqْE-yr3л?ݻghEY9)AT|GREc~Jew*mTdhwF2_Tp 9ۢ9ҍ1zF6T=ݭv y{m6{H< 3EgȊc^5/DMU'[HPj?C#ㅢ0j|clƓ2]Djpc24hq$lgX;p RG<;._0[^Ƴ2p7yo6RX^_J"G i2TU jM<4mof[n endstream endobj 521 0 obj <> stream xk```}G_86 G endstream endobj 523 0 obj <> stream x]U{TSg7%1UD6^(Gh+lQ^Kx(K  ꁊ+(8oP@E16Z+ncr>8go9ߙ{;37opp6Y"-f | 1&˄Gn7n{y0 x/L P\hL9`aS`5p.>׃jTdJ#"#$K-"9>>^A+jjVDtf-RuYGhUk҅:3V魴l1ע5jV4Z m+)KUtdZUKӴUlXf/0[ :V*7d“gS2"lll5ZZoF63͖5j#R06 c\l!#e`J,Sa055 qL4)b p9953&o:o1(%82r7u܅_˄Ke" WlW8li0A,s%-joH!i `w=2[ K|]Yڍ珿Zml%> NTM8g挼zu:̵ےڭ',ڰ:OJ̏Kn%TOl%?ͣu c cK׼Դyjwn%Agݩ-$Gr\&':ް枲 ٭{Jɲb.@T;td[TD =.^"J 2N !-(d=F_9Zw+]L#p+1C좴IxCOx9Exq{ql;Mq< Z ,N >bG2o<@{9 ,Ltx'RU5juU> 5 endstream endobj 525 0 obj <> stream xk```0TdH2J endstream endobj 527 0 obj <> stream xmT}LGt=dbTm-|M6::v?SQZ̥<׿ iAcqc,h3Z]Z`8cEtZh`G4LUJ-3lVF6*f!_JÔ,9AtmBZoGhw_? 0\2/ [VA|7qTg={y2缦޵Ng~s$(S!C))bĤjsjp-S#"Ï&?z_ X@'« =䓥e OL&誤;N<97SRw.vl#G-xE9zG`R M,2ʅ@~TIlaܑiG@]0:Jo2y:ͥ'~p0D=UL&*QjlgÁcP>VJa'0H"_~Ʃ#w剻b^~[@aRq~v 6:6( 67,ls6:M| 94:=4B endstream endobj 529 0 obj <> stream xk`El 0 endstream endobj 491 0 obj <> stream xڵZYsJ}~(ٷ*F҃IDcrwz$ے%)eFt>#OxNE-y"GD1"qw!1h0%&cDɭI\"2Bp B"ź'2XOT2 6Q*D`\Y+T&,VCnk<>42q,!qNHΒ>pz4LsB,#4*6!2pQ_,$ҵ"^XIץ <ZM=$೹يr4e*c,^Se~%TN$9C]04φ[!8* ]Ә7-iUgb3 o*zՍ>М8i°i<5 `&˧jTo4ci/S{E7èGY,J/ ٝaZPS%4>8;< J#i(@blN5;t F7][T(F~*[cI7rLRqZpAFbGJ*=B̚74zIzSl1t]T)1ǹp,kI(wm+I,@ŚJv1>slRSL1A6[[.] EݦmWdED&f+X*nSk @t]QMaP \cq (]lE9YQ#ⶎ*iQĮq2.LNb5Rcp&pWHC6cpN>OekoީC8;'G70qǧ|pyplgQvb*uz?d7{/9;ɮe9{ʎF٨?zw 'Shq{;n/{P"{[6E͒"lc|AsZޑ²StŰu] ~9F~᢬gcpvRIHdS7 ëAp;]Ha82ht9N{šNo8dK@f#4k?(}d/ĝE~ op*Qa=wj); %_)N7;[h1'm裫PGPb(R2~`J&̨Tz)\dPk0eV!VhKH&?~pA_ NE/d[mRit:RqB3ѵB#@nnH_?bI_-Kf#m$iީPb%&O<9X18vd7B{e]7Wwoγ=vv% x5fzPgG%RHh[0yzQ:Ͽ/e f}6`7,g1s"Tm5U7 鰀4obӏ-8P!6N:A{eĎ! &!r&#҇ݎ +V\R'j:RUMߜǵob* S0`>f꠪VP GbnQ#"ߛAxr~V;iCPw?/a9VHˍϑ-n|g(g0c9\2lezyԻMbt(둷6ny 9m뿍x5`#$4p # l[fzayb ٌ_f$l4^'AX@2L3R,n>#D3ᄦ:~J_՜}ṇjap8j[ͷVdu_<*Ymt,g>n2N-)p> z7/{pu (!al .{(oSd)~2 _yѧ;'a;Z[5NU<0 \I{lH)fx9>}>ʷGKWŭu͗)ނ|ĶCGbsl7wIvp_"PjP:nۯN6ݭXWg[(EfvVZ\iǃzK{o{6d>\|X^weI+{+حZP?Z'SHk5}iX~-L2?,ΉX 5(Z endstream endobj 541 0 obj <<744b5d6bbdf620b93a4ca6b2d1258f89>]/Root 1 0 R/Info 2 0 R/Size 542/W[1 3 2]/Filter/FlateDecode/Length 1257>> stream x5WpUU$$pC$!PBHoI B;BҥE:Nf|AGtdttQq|}NnnY;9IwqEЗ aS fs.9Α}zXCbCla`8F`Sԟ0c8aJr,aK `<Lb&c TLtLl\|lX#vv ;c쉽78@\h|{ Cq{ E~a#p_vuWגKp48g8qIϽ 1 ۈ}n`Fp|[YSM- g7س<Ѯdqy'oo٘)na9ṵ̆5XMܦ9֔lWk^-3;bWgruEGܭkޢ+dkަ/Y5Qkޥw5kf ˳fQ\q.ER\qH\O{<8Y \o+Qj\z܀O6f܂[qnwnIJOOxB$KsR5hN[Hߺ֚js"%/Hi~̙$25h.,ۥiTXsƺue!rh59ȚXKC I| + POS!C!s cFaqkh059)9c 9}QY #=O9r4쉽p+om<٘Erb숝3ub7,Xz^&>TCq+xGc28dz3p"NXz_#O2Գ@'pY99138 A=~lɬS]'NySZ'N㹸\Kp.F}7b.GqVz\[pDځUu=SH6v{tu^AyK^y>zi}p5Dk XP^}5D򚟪y,^`߅ק endstream endobj startxref 240462 %%EOF HM-HM-18.0/doc/software-manual.tex000066400000000000000000003744461442026013100166570ustar00rootroot00000000000000\documentclass[a4paper,11pt]{jvetdoc} \usepackage{geometry}[2010/02/12] \usepackage{hyperref} \hypersetup{colorlinks=true, linkcolor=black, % color of internal links (change box color with linkbordercolor) citecolor=black, % color of links to bibliography filecolor=black, % color of file links urlcolor=blue} \usepackage{color,soul} \usepackage[position=bottom]{subfig} \captionsetup[subfloat]{position=top} \usepackage{multirow} \usepackage{dcolumn} \newcolumntype{.}{D{.}{.}{-1}} \usepackage{colortbl} \usepackage{makecell} \usepackage{longtable} \usepackage{array} \usepackage{algorithm2e} \usepackage{amsmath} \urlstyle{same} % code highlighting \usepackage{minted,xcolor} \definecolor{bggray}{gray}{0.95} \setminted{ bgcolor=bggray, xleftmargin=3ex, breaklines=true, fontsize=\footnotesize} \usepackage[strings]{underscore} \usepackage{csquotes} \MakeOuterQuote{"} \EnableQuotes \newcommand\None{} \newcommand\NotSet{} \makeatletter \newcommand{\Option}[1]{\ifx\optOption\@empty\gdef\optOption{#1}\else\g@addto@macro\optOption{ \\ #1}\fi} \newcommand{\ShortOption}[1]{\ifx\optShortOption\@empty\gdef\optShortOption{#1}\else\g@addto@macro\optShortOption{ \\ #1}\fi} \newcommand{\Default}[1]{\ifx\optDefault\@empty\gdef\optDefault{#1}\else\g@addto@macro\optDefault{ \\ #1}\fi} \newcommand{\clearOptions}{\gdef\optOption{}\gdef\optShortOption{}\gdef\optDefault{}} \makeatother \newenvironment{OptionTable}[1]{% \footnotesize \def\arraystretch{1.8} \clearOptions \begin{longtable}{l<{\makecell[tl]{\optOption}}% >{\texttt\bgroup}l<{\makecell[tl]{\optShortOption}\egroup}% c<{\makecell[tc]{\optDefault}}% >{\def\arraystretch{1.0}}p{0.5\textwidth}<{\clearOptions}} \caption{#1} \\ \hspace*{12em}&&\hspace*{8em}&\kill \hline \thead{Option} & \egroup\thead{Shorthand}\bgroup & \thead{Default} & \thead{Description} \\ \hline \endfirsthead \caption[]{#1 (Continued)} \\ \hspace*{12em}&&\hspace*{8em}&\kill \hline \thead{Option} & \egroup\thead{Shorthand}\bgroup & \thead{Default} & \thead{Description} \\ \hline \endhead \multicolumn{4}{r}{Continued...}\\ \hline \endfoot \hline \endlastfoot }{% \hline \end{longtable} } \newenvironment{OptionTableNoShorthand}[2]{% \scriptsize \def\arraystretch{1.8} \clearOptions \begin{longtable}{l<{\makecell[tl]{\optOption}}% c<{\makecell[tc]{\optDefault}}% >{\def\arraystretch{1.0}}p{0.5\textwidth}<{\clearOptions}} \caption{#1} \label{#2} \\ \hspace*{12em}&\hspace*{8em}&\kill \hline \thead{Option} & \thead{Default} & \thead{Description} \\ \hline \endfirsthead \caption[]{#1 (Continued)} \\ \hspace*{12em}&\hspace*{8em}&\kill \hline \thead{Option} & \thead{Default} & \thead{Description} \\ \hline \endhead \multicolumn{3}{r}{Continued...}\\ \hline \endfoot \hline \endlastfoot }{% \hline \end{longtable} } \newenvironment{SEIListTable}[1]{% \scriptsize \def\arraystretch{1.8} \clearOptions \begin{longtable}{c<{\makecell[tl]{\optOption}}% l<{\makecell[tc]{\optDefault}}% >{\def\arraystretch{1.0}}p{0.3\textwidth}<{\clearOptions}} \caption{#1} \\ \hspace*{12em}&\hspace*{8em}&\kill \hline \thead{SEI Number} & \thead{SEI Name} & \thead{Table number of encoder controls, if available} \\ \hline \endfirsthead \caption[]{#1 (Continued)} \\ \hspace*{12em}&\hspace*{8em}&\kill \hline \thead{SEI Number} & \thead{SEI Name} & \thead{Table number of encoder controls, if available} \\ \hline \endhead \multicolumn{3}{r}{Continued...}\\ \hline \endfoot \hline \endlastfoot }{% \hline \end{longtable} } \newenvironment{MacroTable}[1]{% \scriptsize \def\arraystretch{1.3} \clearOptions \begin{longtable}{lcp{0.5\textwidth}} \caption{#1} \\ %\hspace*{12em}&&\hspace*{8em}&\kill \hline \thead{Option} & \thead{Default} & \thead{Description} \\ \hline \endfirsthead \caption[]{#1 (Continued)} \\ \hline \thead{Option} & \thead{Default} & \thead{Description} \\ \hline \endhead \multicolumn{3}{r}{Continued...}\\ \hline \endfoot \hline \endlastfoot }{% \end{longtable} } \title{HM Software Manual} \author{% Frank Bossen \email{frank@bossentech.com} \and David Flynn \email{dflynn@blackberry.com} \and Karl Sharman \email{karl.sharman@eu.sony.com} \and Karsten S\"uhring \email{karsten.suehring@hhi.fraunhofer.de} } \jvetmeeting{} \jvetdocnum{Software Manual} \jvetdocstatus{Software AHG working document} \jvetdocpurpose{Information} \jvetdocsource{AHG chairs} \begin{document} \maketitle \begin{abstract} This document is a user manual describing usage of reference software for the HEVC project. It applies to version 18.0 of the software. \end{abstract} \tableofcontents \listoftables \section{General Information} Reference software is being made available to provide a reference implementation of the HEVC standard being developed by the Joint Collaborative Team on Video Coding (JCT-VC) regrouping experts from ITU-T SG 16 and ISO/IEC SC29 WG11. One of the main goals of the reference software is to provide a basis upon which to conduct experiments in order to determine which coding tools provide desired coding performance. It is not meant to be a particularly efficient implementation of anything, and one may notice its apparent unsuitability for a particular use. It should not be construed to be a reflection of how complex a production-quality implementation of a future HEVC standard would be. This document aims to provide guidance on the usage of the reference software. It is widely suspected to be incomplete and suggestions for improvements are welcome. Such suggestions and general inquiries may be sent to the general JCT-VC email reflector on \url{https://lists.rwth-aachen.de/postorius/lists/jct-vc.lists.rwth-aachen.de/} (registration required). \subsection*{Bug reporting} Bugs should be reported on the issue tracker set up at: \url{https://hevc.hhi.fraunhofer.de/trac/hevc/} \section{Installation and compilation} The software may be retrieved from the GitLab server located at: \url{https://vcgit.hhi.fraunhofer.de/jct-vc/HM} Table~\ref{tab:project-files} lists the compiler environments and versions for which building the software is tested. \begin{table}[ht] \caption{Supported compilers} \label{tab:project-files} \centering \begin{tabular}{ll} \hline \thead{Compiler environment} & \thead{Versions} \\ \hline MS Visual Studio & 2017 and 2019 \\ GCC & 7.3 and 8.3\\ Xcode/clang & latest \\ \hline \end{tabular} \end{table} By default the software is built as 64-bit binaries to be used on a 64-bit OS. This allows the software to use more than 2GB of RAM. The software uses CMake to create platform-specific build files. \subsection {Build instructions for plain CMake (suggested)} \textbf{Note:} A working CMake installation is required for building the software. CMake generates configuration files for the compiler environment/development environment on each platform. The following is a list of examples for Windows (MS Visual Studio), macOS (Xcode) and Linux (make). Open a command prompt on your system and change into the root directory of this project. Create a build directory in the root directory: \begin{minted}{bash} mkdir build \end{minted} Use one of the following CMake commands, based on your platform. Feel free to change the commands to satisfy your needs. \textbf{Windows Visual Studio 2015 64 Bit:} \begin{minted}{bash} cd build cmake .. -G "Visual Studio 14 2015 Win64" \end{minted} Then open the generated solution file in MS Visual Studio. \textbf{macOS Xcode:} \begin{minted}{bash} cd build cmake .. -G "Xcode" \end{minted} Then open the generated work space in Xcode. \textbf{Linux} For generating Linux Release Makefile: \begin{minted}{bash} cd build cmake .. -DCMAKE_BUILD_TYPE=Release \end{minted} For generating Linux Debug Makefile: \begin{minted}{bash} cd build cmake .. -DCMAKE_BUILD_TYPE=Debug \end{minted} Then type \begin{minted}{bash} make -j \end{minted} to build the software. For more details, refer to the CMake documentation: \url{https://cmake.org/cmake/help/latest/} \subsection {Build instructions for make} \textbf{Note:} The build instructions in this section require the make tool and Python to be installed, which are part of usual Linux and macOS environments. See section \ref{windowsinstall} for installation instruction for Python and GnuWin32 on Windows. Open a command prompt on your system and change into the root directory of this project. To use the default system compiler simply call: \begin{minted}{bash} make all \end{minted} For MSYS2 and MinGW: Open an MSYS MinGW 64-Bit terminal and change into the root directory of this project. Call: \begin{minted}{bash} make all toolset=gcc \end{minted} \subsection{Tool Installation on Windows} \label{windowsinstall} Download CMake: \url{http://www.cmake.org/} and install it. Python and GnuWin32 are not mandatory, but they simplify the build process for the user. \begin{table}[ht] \footnotesize \centering \begin{tabular}{ll} \hline Python & \url{https://www.python.org/downloads/release/python-371/} \\ GnuWin32 & \url{https://sourceforge.net/projects/getgnuwin32/files/getgnuwin32/0.6.30/GetGnuWin32-0.6.3.exe/download} \\ \hline \end{tabular} \end{table} To use MinGW, install MSYS2: \url{http://repo.msys2.org/distrib/msys2-x86_64-latest.exe} Installation instructions: \url{https://www.msys2.org/} Install the needed toolchains: \begin{minted}{bash} pacman -S --needed base-devel mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain git subversion mingw-w64-i686-cmake mingw-w64-x86_64-cmake \end{minted} %%%% %%%% %%%% \section{Using the encoder} \begin{minted}{bash} TAppEncoder [--help] [-c config.cfg] [--parameter=value] \end{minted} \begin{table}[ht] \footnotesize \centering \begin{tabular}{lp{0.5\textwidth}} \hline \thead{Option} & \thead{Description} \\ \hline \texttt{--help} & Prints parameter usage. \\ \texttt{-c} & Defines configuration file to use. Multiple configuration files may be used with repeated --c options. \\ \texttt{--}\emph{parameter}\texttt{=}\emph{value} & Assigns value to a given parameter as further described below. Some parameters are also supported by shorthand "--\em{opt}~\emph{value}". These are shown in brackets after the parameter name in the tables of this document\\ \hline \end{tabular} \end{table} Sample configuration files are provided in the cfg/ folder. Parameters are defined by the last value encountered on the command line. Therefore if a setting is set via a configuration file, and then a subsequent command line parameter changes that same setting, the command line parameter value will be used. \subsection{GOP structure table} \label{sec:gop-structure} Defines the cyclic GOP structure that will be used repeatedly throughout the sequence. The table should contain GOPSize lines, named Frame1, Frame2, etc. The frames are listed in decoding order, so Frame1 is the first frame in decoding order, Frame2 is the second and so on. Among other things, the table specifies all reference pictures kept by the decoder for each frame. This includes pictures that are used for reference for the current picture as well as pictures that will be used for reference in the future. The encoder will not automatically calculate which pictures have to be kept for future references, they must be specified. Note that some specified reference frames for pictures encoded in the very first GOP after an IDR frame might not be available. This is handled automatically by the encoder, so the reference pictures can be given in the GOP structure table as if there were infinitely many identical GOPs before the current one. Each line in the table contains the parameters used for the corresponding frame, separated by whitespace: \begin{itemize} \item[]\textbf{Type}: Slice type, can be either I, P or B. \item[]\textbf{POC}: Display order of the frame within a GOP, ranging from 1 to GOPSize. \item[]\textbf{QPOffset}: QP offset is added to the QP parameter to set the final QP value to use for this frame. \item[]\textbf{QPOffsetModelOff}: Offset parameter to a linear model to adjust final QP based on QP + QPoffset. \item[]\textbf{QPOffsetModelScale}: Scale parameter to a linear model to adjust final QP based on QP + QPoffset. \item[]\textbf{SliceCbQPOffset}: The slice-level Cb QP offset. \item[]\textbf{SliceCrQPOffset}: The slice-level Cr QP offset. \item[]\textbf{QPFactor}: Weight used during rate distortion optimization. Higher values mean lower quality and less bits. Typical range is between 0.3 and 1. \item[]\textbf{tcOffsetDiv2}: In-loop deblocking filter parameter tcOffsetDiv2 is added to the base parameter LoopFilterTcOffset_div2 to set the final tc_offset_div2 parameter for this picture signalled in the slice segment header. The final value of tc_offset_div2 shall be an integer number in the range $-6..6$. \item[]\textbf{betaOffsetDiv2}: In-loop deblocking filter parameter betaOffsetDiv2 is added to the base parameter LoopFilterBetaOffset_div2 to set the final beta_offset_div2 parameter for this picture signalled in the slice segment header. The final value of beta_offset_div2 shall be an integer number in the range $-6..6$. \item[]\textbf{temporal_id}: Temporal layer of the frame. A frame cannot predict from a frame with a higher temporal id. If a frame with higher temporal IDs is listed among a frame's reference pictures, it is not used, but is kept for possible use in future frames. \item[]\textbf{num_ref_pics_active}: Size of reference picture lists L0 and L1, indicating how many reference pictures in each direction that are used during coding. \item[]\textbf{num_ref_pics}: The number of reference pictures kept for this frame. This includes pictures that are used for reference for the current picture as well as pictures that will be used for reference in the future. \item[]\textbf{reference_pictures}: A space-separated list of num_ref_pics integers, specifying the POC of the reference pictures kept, relative the POC of the current frame. The picture list shall be ordered, first with negative numbers from largest to smallest, followed by positive numbers from smallest to largest (e.g. \verb|-1 -3 -5 1 3|). Note that any pictures not supplied in this list will be discarded and therefore not available as reference pictures later. \item[]\textbf{predict}: Defines the value of the syntax element inter_ref_pic_set_prediction_flag. A value of 0 indicates that the reference picture set is encoded without inter RPS prediction and the subsequent parameters deltaRIdx$-1$, deltaRPS, num_ref_idcs and Reference_idcs are ignored and do not need to be present. A value of 1 indicates that the reference picture set is encoded with inter prediction RPS using the subsequent parameters deltaRIdx$-1$, deltaRPS, num_ref_idcs and Reference_idcs in the line. A value of 2 indicates that the reference picture set is encoded with inter RPS but only the deltaRIdx$-1$ parameters is needed. The deltaRPS, num_ref_idcs and Reference_idcs values are automatically derived by the encoder based on the POC and refPic values of the current line and the RPS pointed to by the deltaRIdx$-1$ parameters. \item[]\textbf{deltaRIdx$-1$}: The difference between the index of the curent RPS and the predictor RPS minus 1. \item[]\textbf{deltaRPS}: The difference between the POC of the predictor RPS and POC the current RPS. \item[]\textbf{num_ref_idcs}: The number of ref_idcs to encode for the current RPS. The value is equal to the value of num_ref_pics of the predictor RPS plus 1. \item[]\textbf{reference_idcs}: A space-separated list of num_ref_idcs integers, specifying the ref idcs of the inter RPS prediction. The value of ref_idcs may be 0, 1 or 2 indicating that the reference picture is a reference picture used by the current picture, a reference picture used for future picture or not a reference picture anymore, respectively. The first num_ref_pics of ref_idcs correspond to the Reference pictures in the predictor RPS. The last ref_idcs corresponds to the predictor picture. \end{itemize} For example, consider the coding structure of Figure~\ref{fig:gop-example}. This coding structure is of size 4. The pictures are listed in decoding order. Frame1 shall therefore describe picture with $\textrm{POC}=4$. It references picture 0, and therefore has $-4$ as a reference picture. Similarly, Frame2 has a POC of 2, and since it references pictures 0 and 4, its reference pictures are listed as \verb|-2 2|. Frame3 is a special case: even though it only references pictures with POC 0 and 2, it also needs to include the picture with POC 4, which must be kept in order to be used as a reference picture in the future. The reference picture list for Frame3 therefore becomes \verb|-1 1 3|. Frame4 has a POC of 3 and its list of reference pictures is \verb|-1 1|. \begin{figure}[h] \caption{A GOP structure} \label{fig:gop-example} \centering \includegraphics[width=0.7\textwidth]{gop-structure-example} \end{figure} Inter RPS prediction may be used for Frame2, Frame3 and Frame4, hence the predict parameter is set to 1 for these frames. Frame2 uses Frame1 as the predictor hence the deltaRIdx$-1$ is 0. Similarly for Frame3 and Frame4 which use Frame2 and Frame3 as predictors, respectively. The deltaRPS is equal to the POC of the predictor minus the POC of the current picture, therefore the deltaRPS for Frame2 is $4 -2 = 2$, for Frame3 is $2 - 1 = 1$ and for Frame4 is $1 - 3 = -2$. In Frame2, reference pictures with POC 0 and 2 are used, so the reference idcs for Frame2 are \verb|1 1| indicating that the reference picture, $-4$, in Frame1 is still a reference picture in Frame2 and Frame1 is also a reference picture in Frame2. The reference idcs for Frame3 are \verb|1 1 1|. The first and second “1”s indicating that the reference pictures "$-2$ $2$" in Frame2 are still reference pictures in Frame3 and the last “1” indicating that Frame2 is also a reference picture in Frame3. In Frame 4, the reference idcs are \verb|0 1 1 0|. The first “0” indicates that the reference pictures “-1” in Frame 3 is no longer a reference picture in Frame4. The next two “1”s indicate that the reference pictures “$1$ $3$” are now reference pictures of Frame4. The final “0” indicates that Frame3 is not a reference picture. In order to specify this to the encoder, the parameters in Table~\ref{tab:gop-example} could be used. \begin{table}[ht] \footnotesize \caption{GOP structure example} \label{tab:gop-example} \centering \begin{tabular}{lrrrr} \hline \thead{} & \thead{Frame1} & \thead{Frame2} & \thead{Frame3} & \thead{Frame4} \\ \hline Type & P & B & B & B \\ POC & 4 & 2 & 1 & 3 \\ QPOffset & 1 & 2 & 3 & 3 \\ QPOffsetModelOff & 0.0 & 0.0 & 0.0 & 0.0 \\ QPOffsetModelScale & 0.0 & 0.0 & 0.0 & 0.0 \\ SliceCbQPOffset & 0 & 0 & 0 & 0 \\ SliceCrQPOffset & 0 & 0 & 0 & 0 \\ QPfactor & 0.5 & 0.5 & 0.5 & 0.5 \\ tcOffsetDiv2 & 0 & 1 & 2 & 2 \\ betaOffsetDiv2 & 0 & 0 & 0 & 0 \\ temporal_id & 0 & 1 & 2 & 2 \\ num_ref_pics_active & 1 & 1 & 1 & 1 \\ num_ref_pics & 1 & 2 & 3 & 2 \\ reference_pictures & $-$4 & $-$2 2 & $-$1 1 3 & $-$1 1 \\ predict & 0 & 1 & 1 & 1 \\ deltaRIdx$-$1 & & 0 & 0 & 0 \\ deltaRPS & & 2 & 1 & $-$2 \\ num_ref_idcs & & 2 & 3 & 4 \\ reference_idcs & & 1 1 & 1 1 1 & 0 1 1 0 \\ \hline \end{tabular} \end{table} Here, the frames used for prediction have been given higher quality by assigning a lower QP offset. Also, the non-reference frames have been marked as belonging to a higher temporal layer, to make it possible to decode only every other frame. Note: each line should contain information for one frame, so this configuration would be specified as: \begin{verbatim} Frame1: P 4 1 0 0 0.5 0 0 0 1 1 -4 0 Frame2: B 2 2 0 0 0.5 1 0 1 1 2 -2 2 1 0 2 2 1 1 Frame3: B 1 3 0 0 0.5 2 0 2 1 3 -1 1 3 1 0 1 3 1 1 1 Frame4: B 3 3 0 0 0.5 2 0 2 1 2 -1 1 1 0 -2 4 0 1 1 0 \end{verbatim} The values of deltaRIdx$-1$, deltaRPS, num_ref_idcs and reference idcs of Frame$K$ can be derived from the POC value of Frame$_K$ and the POC, num_ref_pics and reference_pictures values of Frame$_M$, where $K$ is the index of the RPS to be inter coded and the $M$ is the index of the reference RPS, as follows. \setlength{\algomargin}{2em} \begin{algorithm}[ht] \SetKwData{deltaRIdx}{deltaRIdx} \SetKwData{deltaRPS}{deltaRPS} \SetKwData{numrefidcs}{num_ref_idcs} \SetKwData{numrefpics}{num_ref_pics} \SetKwData{referencepictures}{reference_pictures} \SetKwData{referenceidcs}{reference_idcs} \SetKwData{POC}{POC} $\deltaRIdx_K - 1 \leftarrow K - M - 1$ \; $\deltaRPS_K \leftarrow \POC_M - \POC_K$ \; $\numrefidcs_K \leftarrow \numrefpics_M + 1$ \; \For{$j \leftarrow 0$ \KwTo $\numrefpics_M$}{ \For{$i \leftarrow 0$ \KwTo $\numrefidcs_K$}{ \eIf{$\referencepictures_{M,j} + \deltaRPS_K == \referencepictures_{K,i}$}{ \lIf{$\referencepictures_{K,i}$ is used by the current frame}{ $\referenceidcs_{K,j} = 1$} \; \lElse{$\referenceidcs_{K,j} = 2$} \; }{ $\referenceidcs_K[j] = 0$ \; } } } \tcc{$\referencepictures_{M,\numrefpics_M}$ does not exist and is assumed to be 0} \end{algorithm} Note: The above (automatic) generation of the inter RPS parameter values has been integrated into the encoder, and is activated by the value of predict $= 2$ followed by the value of deltaRIdx$-1$, only, as described above. %%%% %%%% %%%% \newgeometry{tmargin=1.6cm,lmargin=1cm,rmargin=1cm,bmargin=1in,nohead} \subsection{Encoder parameters} %% %% File, I/O and source parameters %% Shorthand alternatives for the parameter that can be used on the command line are shown in brackets after the parameter name. \begin{OptionTableNoShorthand}{File, I/O and source parameters.}{tab:fileIO} \Option{InputFile (-i)} & %\ShortOption{-i} & \Default{\NotSet} & Specifies the input video file. Video data must be in a raw 4:2:0, or 4:2:2 planar format, 4:4:4 planar format (Y$'$CbCr, RGB or GBR), or in a raw 4:0:0 format. Note: When the bit depth of samples is larger than 8, each sample is encoded in 2 bytes (little endian, LSB-justified). \\ \Option{InputPathPrefix (-ipp)} & %\ShortOption{-ipp} & \Default{\NotSet} & Specifies a string to prepend to the input video file string, specified using -i. \\ \Option{BitstreamFile (-b)} & %\ShortOption{-b} & \Default{\NotSet} & Specifies the output coded bit stream file. \\ \Option{ReconFile (-o)} & %\ShortOption{-o} & \Default{\NotSet} & Specifies the output locally reconstructed video file. \\ \Option{SourceWidth (-wdt)}% \Option{SourceHeight (-hgt)} & %\ShortOption{-wdt}% %\ShortOption{-hgt} & \Default{0}% \Default{0} & Specifies the width and height of the input video in luma samples. \\ \Option{InputBitDepth} & %\ShortOption{\None} & \Default{8} & Specifies the bit depth of the input video. \\ \Option{MSBExtendedBitDepth} & %\ShortOption{\None} & \Default{0} & Extends the input video by adding MSBs of value 0. When 0, no extension is applied and the InputBitDepth is used. The MSBExtendedBitDepth becomes the effective file InputBitDepth for subsequent processing. \\ \Option{InternalBitDepth} & %\ShortOption{\None} & \Default{0} & Specifies the bit depth used for coding. When 0, the setting defaults to the value of the MSBExtendedBitDepth. If the input video is a different bit depth to InternalBitDepth, it is automatically converted by: \begin{displaymath} \left\lfloor \frac{\mathrm{Pel} * 2^{\mathrm{InternalBitDepth}}}{ 2^{\mathrm{MSBExtendedBitDepth}}} \right\rfloor \end{displaymath} Note: The effect of this option is as if the input video is externally converted to the MSBExtendedBitDepth and then to the InternalBitDepth and then coded with this value as InputBitDepth. The codec has no notion of different bit depths. \\ \Option{OutputBitDepth} & %\ShortOption{\None} & \Default{0} & Specifies the bit depth of the output locally reconstructed video file. When 0, the setting defaults to the value of InternalBitDepth. Note: This option has no effect on the decoding process. \\ \Option{InputBitDepthC}% \Option{MSBExtendedBitDepthC}% \Option{InternalBitDepthC}% \Option{OutputBitDepthC} & %\ShortOption{\None} & \Default{0}% \Default{0}% \Default{0}% \Default{0} & Specifies the various bit-depths for chroma components. These only need to be specified if non-equal luma and chroma bit-depth processing is required. When 0, the setting defaults to the corresponding non-Chroma value. \\ \Option{InputColourSpaceConvert} & %\ShortOption{\None} & \Default{\NotSet} & The colour space conversion to apply to input video. Permitted values are: \par \begin{tabular}{lp{0.3\textwidth}} UNCHANGED & No colour space conversion is applied \\ YCbCrToYCrCb & Swap the second and third components \\ YCbCrtoYYY & Set the second and third components to the values in the first \\ RGBtoGBR & Reorder the three components \\ \end{tabular} \par If no value is specified, no colour space conversion is applied. The list may eventually also include RGB to YCbCr or YCgCo conversions. \\ \Option{SNRInternalColourSpace} & %\ShortOption{\None} & \Default{false} & When this is set true, then no colour space conversion is applied prior to PSNR calculation, otherwise the inverse of InputColourSpaceConvert is applied. \\ \Option{OutputInternalColourSpace} & %\ShortOption{\None} & \Default{false} & When this is set true, then no colour space conversion is applied to the reconstructed video, otherwise the inverse of InputColourSpaceConvert is applied. \\ \Option{InputChromaFormat} & %\ShortOption{\None} & \Default{420} & Specifies the chroma format used in the input file. Permitted values (depending on the profile) are 400, 420, 422 or 444. \\ \Option{ChromaFormatIDC (-cf)} & %\ShortOption{-cf} & \Default{0} & Specifies the chroma format to use for processing. Permitted values (depending on the profile) are 400, 420, 422 or 444; the value of 0 indicates that the value of InputChromaFormat should be used instead. \\ \Option{MSEBasedSequencePSNR} & %\ShortOption{\None} & \Default{false} & When 0, the PSNR output is a linear average of the frame PSNRs; when 1, additional PSNRs are output which are formed from the average MSE of all the frames. The latter is useful when coding near-losslessly, where occasional frames become lossless. \\ \Option{PrintHexPSNR} & %\ShortOption{\None} & \Default{false} & When 1, each POC line will include the 64-bit hexadecimal representation of the PSNR for each channel. This allows some types of simulations to be split into sub-simulations and the results later combined without loss of accuracy. \\ \Option{PrintFrameMSE} & %\ShortOption{\None} & \Default{false} & When 1, the Mean Square Error (MSE) values of each frame will also be output alongside the default PSNR values. \\ \Option{PrintSequenceMSE} & %\ShortOption{\None} & \Default{false} & When 1, the Mean Square Error (MSE) values of the entire sequence will also be output alongside the default PSNR values. \\ \Option{PrintMSSSIM} & %\ShortOption{\None} & \Default{false} & When 1, the multi-scale structural similarity (MS-SSIM) will also be output alongside the PSNR values. \\ \Option{xPSNREnableFlag (-xPS} & %\ShortOption{\None} & \Default{false} & When 1, the cross component PSNR is calculated, using the weights provided with xPSNRYWeight, xPSNRCbWeight and xPSNRCrWeight. \\ \Option{xPSNRYWeight (-xPS0)} & %\ShortOption{\None} & \Default{1.0} & Specifies the xPSNR weighting factor for Y. \\ \Option{xPSNRCbWeight (-xPS1)} & %\ShortOption{\None} & \Default{1.0} & Specifies the xPSNR weighting factor for Cb. \\ \Option{xPSNRCrWeight (-xPS2)} & %\ShortOption{\None} & \Default{1.0} & Specifies the xPSNR weighting factor for Cr. \\ \Option{SummaryOutFilename} & %\ShortOption{\None} & \Default{false} & Filename to use for producing summary output file. If empty, do not produce a file. \\ \Option{SummaryPicFilenameBase} & %\ShortOption{\None} & \Default{false} & Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended. If empty, do not produce a file. \\ \Option{SummaryVerboseness} & %\ShortOption{\None} & \Default{false} & Specifies the level of the verboseness of the text output. \\ \Option{CabacZeroWordPaddingEnabled} & %\ShortOption{\None} & \Default{false} & When 1, CABAC zero word padding will be enabled. This is currently not the default value for the setting. \\ \Option{ConformanceWindowMode} & %\ShortOption{\None} & \Default{0} & Specifies how the parameters related to the conformance window are interpreted (cropping/padding). The following modes are available: \par \begin{tabular}{cp{0.43\textwidth}} 0 & No cropping / padding \\ 1 & Automatic padding to the next minimum CU size \\ 2 & Padding according to parameters HorizontalPadding and VerticalPadding \\ 3 & Cropping according to parameters ConfWinLeft, ConfWinRight, ConfWinTop and ConfWinBottom \\ \end{tabular} \\ \Option{HorizontalPadding (-pdx)}% \Option{VerticalPadding (-pdy)} & %\ShortOption{-pdx}% %\ShortOption{-pdy} & \Default{0} & Specifies the horizontal and vertical padding to be applied to the input video in luma samples when ConformanceWindowMode is 2. Must be a multiple of the chroma resolution (e.g. a multiple of two for 4:2:0). \\ \Option{ConfWinLeft}% \Option{ConfWinRight}% \Option{ConfWinTop}% \Option{ConfWinBottom} & %\ShortOption{\None} & \Default{0} & Specifies the horizontal and vertical cropping to be applied to the input video in luma samples when ConformanceWindowMode is 3. Must be a multiple of the chroma resolution (e.g. a multiple of two for 4:2:0). \\ \Option{FrameRate (-fr)} & %\ShortOption{-fr} & \Default{0} & Specifies the frame rate of the input video. Note: This option only affects the reported bit rates. \\ \Option{FrameSkip (-fs)} & %\ShortOption{-fs} & \Default{0} & Specifies a number of frames to skip at beginning of input video file. \\ \Option{FramesToBeEncoded (-f)} & %\ShortOption{-f} & \Default{0} & Specifies the number of frames to be encoded (see note regarding TemporalSubsampleRatio). When 0, all frames are coded. \\ \Option{TemporalSubsampleRatio (-ts)} & %\ShortOption{-fs} & \Default{1} & Temporally subsamples the input video sequence. A value of $N$ will skip $(N-1)$ frames of input video after each coded input video frame. Note the FramesToBeEncoded does not account for the temporal skipping of frames, which will reduce the number of frames encoded accordingly. The reported bit rates will be reduced and VUI information is scaled so as to present the video at the correct speed. The minimum and default value is 1. \\ \Option{FieldCoding} & %\ShortOption{\None} & \Default{false} & When 1, indicates that field-based coding is to be applied. \\ \Option{TopFieldFirst (-Tff)} & %\ShortOption{\None} & \Default{0} & Indicates the order of the fields packed into the input frame. When 1, the top field is temporally first. \\ \Option{ClipInputVideoToRec709Range} & %\ShortOption{\None} & \Default{0} & If 1 then clip input video to the Rec. 709 Range on loading when InternalBitDepth is less than MSBExtendedBitDepth. \\ \Option{ClipOutputVideoToRec709Range} & %\ShortOption{\None} & \Default{0} & If 1 then clip output video to the Rec. 709 Range on saving when OutputBitDepth is less than InternalBitDepth. \\ \Option{EfficientFieldIRAPEnabled} & %\ShortOption{\None} & \Default{1} & Enable to code fields in a specific, potentially more efficient, order. \\ \Option{HarmonizeGopFirstFieldCoupleEnabled} & %\ShortOption{\None} & \Default{1} & Enables harmonization of Gop first field couple. \\ \Option{AccessUnitDelimiter} & %\ShortOption{\None} & \Default{0} & Add Access Unit Delimiter NAL units between all Access Units. \\ \end{OptionTableNoShorthand} %% %% profile, level and conformance options %% \begin{OptionTableNoShorthand}{Profile and level parameters}{tab:profile} \Option{Profile} & %\ShortOption{\None} & \Default{none} & Specifies the profile to which the encoded bitstream complies. Valid HEVC Ver. 1 values are: none, main, main10, main-still-picture Valid HEVC Ver. 2 (RExt) values are: main-RExt, high-throughput-RExt, monochrome, monochrome12, monochrome16, main12, main_422_10, main_422_12, main_444, main_444_10, main_444_12, main_444_16, main_intra, main_10_intra, main_12_intra, main_422_10_intra, main_422_12_intra, main_444_intra, main_444_10_intra, main_444_12_intra, main_444_16_intra, high_throughput_444_16_intra. In addition, the following profiles strings are available: high_throughput_444, high_throughput_444_10, high_throughput_444_14. When main-RExt or high-throughput-RExt is specified, the constraint flags are either manually specified, or calculated via the other supplied settings. Compatibility flags are automatically determined according to the profile. NB: There is currently only limited validation that the encoder configuration complies with the profile, level and tier constraints. \\ \Option{Level} & %\ShortOption{\None} & \Default{none} & Specifies the level to which the encoded bitstream complies. Valid values are: none, 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2, 8.5 NB: There is currently only limited validation that the encoder configuration complies with the profile, level and tier constraints. \\ \Option{Tier} & %\ShortOption{\None} & \Default{main} & Specifies the level tier to which the encoded bitsream complies. Valid values are: main, high. NB: There is currently only limited validation that the encoder configuration complies with the profile, level and tier constraints. \\ \Option{MaxBitDepthConstraint} & %\ShortOption{\None} & \Default{0} & For --profile=main-RExt, specifies the value to use to derive the general_max_bit_depth constraint flags for RExt profiles; when 0, use $\max(InternalBitDepth, InternalBitDepthC)$ \\ \Option{MaxChromaFormatConstraint} & %\ShortOption{\None} & \Default{0} & For --profile=main-RExt, specifies the chroma-format to use for the general profile constraints for RExt profiles; when 0, use the value of ChromaFormatIDC. \\ \Option{IntraConstraintFlag} & %\ShortOption{\None} & \Default{false} & For --profile=main-RExt, specifies the value of general_intra_constraint_flag to use for RExt profiles. \\ \Option{OnePictureOnlyConstraintFlag} & %\ShortOption{\None} & \Default{false} & For --profile=main-RExt, specifies the value of general_one_picture_only_constraint_flag to use for RExt profiles. \\ \Option{LowerBitRateConstraintFlag} & %\ShortOption{\None} & \Default{true} & Specifies the value of general_lower_bit_constraint_flag to use for RExt profiles. \\ \Option{ProgressiveSource} & %\ShortOption{\None} & \Default{false} & Specifies the value of general_progressive_source_flag \\ \Option{InterlacedSource} & %\ShortOption{\None} & \Default{false} & Specifies the value of general_interlaced_source_flag \\ \Option{NonPackedSource} & %\ShortOption{\None} & \Default{false} & Specifies the value of general_non_packed_constraint_flag \\ \Option{FrameOnly} & %\ShortOption{\None} & \Default{false} & Specifies the value of general_frame_only_constraint_flag \\ \end{OptionTableNoShorthand} %% %% Unit definition parameters %% \begin{OptionTableNoShorthand}{Unit definition parameters}{tab:unit} \Option{MaxCUWidth} & %\ShortOption{\None} & \Default{64} & Defines the maximum CU width. \\ \Option{MaxCUHeight} & %\ShortOption{\None} & \Default{64} & Defines the maximum CU height. \\ \Option{MaxCUSize (-s)} & %\ShortOption{\None} & \Default{64} & Defines the maximum CU size. \\ \Option{MaxPartitionDepth (-h)} & %\ShortOption{-h} & \Default{4} & Defines the depth of the CU tree. \\ \Option{QuadtreeTULog2MaxSize} & %\ShortOption{\None} & \Default{6 \\ ($= \mathrm{log}_2(64)$)} & Defines the Maximum TU size in logarithm base 2. \\ \Option{QuadtreeTULog2MinSize} & %\ShortOption{\None} & \Default{2 \\ ($= \mathrm{log}_2(4)$)} & Defines the Minimum TU size in logarithm base 2. \\ \Option{QuadtreeTUMaxDepthIntra} & %\ShortOption{\None} & \Default{1} & Defines the depth of the TU tree for intra CUs. \\ \Option{QuadtreeTUMaxDepthInter} & %\ShortOption{\None} & \Default{2} & Defines the depth of the TU tree for inter CUs. \\ \end{OptionTableNoShorthand} %% %% Coding structure parameters %% \begin{OptionTableNoShorthand}{Coding structure parameters}{tab:coding-structure} \Option{IntraPeriod (-ip)} & %\ShortOption{-ip} & \Default{$-1$} & Specifies the intra frame period. A value of $-1$ implies an infinite period. \\ \Option{DecodingRefreshType (-dr)} & %\ShortOption{-dr} & \Default{0} & Specifies the type of decoding refresh to apply at the intra frame period picture. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Applies an I picture (not a intra random access point). \\ 1 & Applies a CRA intra random access point (open GOP). \\ 2 & Applies an IDR intra random access point (closed GOP). \\ 3 & Use recovery point SEI messages to indicate random access. \\ \end{tabular} \\ \Option{GOPSize (-g)} & %\ShortOption{-g} & \Default{1} & Specifies the size of the cyclic GOP structure. \\ \Option{ReWriteParamSetsFlag} & %\ShortOption{\None} & \Default{1} & When enabled, VPS, SPS and PPS are repeated in front of every IRAP picture. \\ \Option{Frame\emph{N}} & %\ShortOption{\None} & \Default{\NotSet} & Multiple options that define the cyclic GOP structure that will be used repeatedly throughout the sequence. The table should contain GOPSize elements. \par See section~\ref{sec:gop-structure} for further details. \\ \end{OptionTableNoShorthand} %% %% Motion estimation parameters %% \begin{OptionTableNoShorthand}{Motion estimation parameters}{tab:motion-estimation} \Option{FastSearch} & %\ShortOption{\None} & \Default{1} & Enables or disables the use of a fast motion search. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Full search method \\ 1 & Fast search method - TZSearch\\ 2 & Predictive motion vector fast search method \\ 3 & Extended TZSearch method \\ \end{tabular} \\ \Option{SearchRange (-sr)} & %\ShortOption{-sr} & \Default{96} & Specifies the search range used for motion estimation. Note: the search range is defined around a predictor. Motion vectors derived by the motion estimation may thus have values larger than the search range. \\ \Option{BipredSearchRange} & %\ShortOption{\None} & \Default{4} & Specifies the search range used for bi-prediction refinement in motion estimation. \\ \Option{ClipForBiPredMEEnabled} & %\ShortOption{\None} & \Default{0} & Enables clipping in the Bi-Pred ME, which prevents values over- or under-flowing. It is usually disabled to reduce encoder run-time. \\ \Option{FastMEAssumingSmootherMVEnabled} & %\ShortOption{\None} & \Default{0} & Enables fast ME assuming a smoother MV. \\ \Option{HadamardME} & %\ShortOption{\None} & \Default{true} & Enables or disables the use of the Hadamard transform in fractional-pel motion estimation. \par \begin{tabular}{cp{0.45\textwidth}} 0 & SAD for cost estimation \\ 1 & Hadamard for cost estimation \\ \end{tabular} \\ \Option{ASR} & %\ShortOption{\None} & \Default{false} & Enables or disables the use of adaptive search ranges, where the motion search range is dynamically adjusted according to the POC difference between the current and the reference pictures. \begin{displaymath} \resizebox{\hsize}{!}{$ \mathrm{SearchRange}’ = \mathrm{Round}\left( \mathrm{SearchRange} * \mathrm{ADAPT\_SR\_SCALE} * \frac{\mathrm{abs}( \mathrm{POCcur} - \mathrm{POCref} )}{ \mathrm{RateGOPSize}}\right) $} \end{displaymath} \\ \Option{MaxNumMergeCand} & %\ShortOption{\None} & \Default{5} & Specifies the maximum number of merge candidates to use. \\ \Option{DisableIntraInInter} & %\ShortOption{\None} & \Default{0} & Flag to disable intra PUs in inter slices. \\ \end{OptionTableNoShorthand} %% %% Mode decision parameters %% \begin{OptionTableNoShorthand}{Mode decision parameters}{tab:mode-decision} \Option{LambdaModifier$N$ (-LM$N$)} & %\ShortOption{-LM$N$} & \Default{1.0} & Specifies a value that is multiplied with the Lagrange multiplier $\lambda$, for use in the rate-distortion optimised cost calculation when encoding temporal layer~$N$. If LambdaModifierI is specified, then LambdaModifierI will be used for intra pictures. \par $N$ may be in the range 0 (inclusive) to 7 (exclusive). \\ \Option{LambdaModifierI (-LMI)} & %\ShortOption{-LMI} & \Default{} & Specifies one or more of the LambdaModifiers to use intra pictures at each of the temporal layers. If not present, then the LambdaModifier$N$ settings are used instead. If the list of values (comma or space separated) does not include enough values for each of the temporal layers, the last value is repeated as required. \\ \Option{IQPFactor (-IQF)} & %\ShortOption{-IQF} & \Default{-1} & Specifies the QP factor to be used for intra pictures during the lambda computation. (The values specified in the GOP structure are only used for inter pictures). If negative (default), the following equation is used to derive the value: \par $IQP_{factor}=0.57*(1.0-Max(0.5, Min(0.0, 0.05*s)))$ \par where $s = Int(isField ? (GS-1)/2 : GS-1)$ and $GS$ is the gop size. \\ \Option{ECU} & %\ShortOption{\None} & \Default{false} & Enables or disables the use of early CU determination. When enabled, skipped CUs will not be split further. \\ \Option{CFM} & %\ShortOption{\None} & \Default{false} & Enables or disables the use of Cbf-based fast encoder mode. When enabled, once a 2Nx2N CU has been evaluated, if the RootCbf is 0, further PU splits will not be evaluated. \\ \Option{ESD} & %\ShortOption{\None} & \Default{false} & Enables or disables the use of early skip detection. When enabled, the skip mode will be tested before any other. \\ \Option{FEN} & %\ShortOption{\None} & \Default{0} & Controls the use of different fast encoder coding tools. The following tools are supported in different combinations: \par \begin{tabular}{cp{0.45\textwidth}} a & In the SAD computation for blocks having size larger than 8, only the lines of even rows in the block are considered. \\ b & The number of iterations used in the bi-directional motion vector refinement in the motion estimation process is reduced from 4 to 1. \\ \end{tabular} Depending on the value of the parameter, the following combinations are supported: \par \begin{tabular}{cp{0.45\textwidth}} 0 & Disable all modes \\ 1 & Use both a \& b tools\\ 2 & Use only tool b \\ 3 & Use only tool a \\ \end{tabular} \\ \Option{FDM} & %\ShortOption{\None} & \Default{true} & Enables or disables the use of fast encoder decisions for 2Nx2N merge mode. When enabled, the RD cost for the merge mode of the current candidate is not evaluated if the merge skip mode was the best merge mode for one of the previous candidates. \\ \Option{RDpenalty} & %\ShortOption{\None} & \Default{0} & RD-penalty for 32x32 TU for intra in non-intra slices. Enabling this parameter can reduce the visibility of CU boundaries in the coded picture. \par \begin{tabular}{cp{0.45\textwidth}} 0 & No RD-penalty \\ 1 & RD-penalty \\ 2 & Maximum RD-penalty (no 32x32 TU)\\ \end{tabular} \\ \end{OptionTableNoShorthand} %% %% Quantization parameters %% \begin{OptionTableNoShorthand}{Quantization parameters}{tab:quantization} \Option{QP (-q)} & %\ShortOption{-q} & \Default{30} & Specifies the base value of the quantization parameter. \\ \Option{QPIncrementFrame (-qpif)} & \Default{\NotSet} & If a source file frame number is specified, the internal QP will be incremented for all POCs associated with source frames beyond and including that frame. If empty, do not increment. \\ \Option{IntraQPOffset} & %\ShortOption{\None} & \Default{0} & Specifies a QP offset from the base QP value to be used for intra frames. \\ \Option{LambdaFromQpEnable} & %\ShortOption{\None} & \Default{false} & When enabled, the $\lambda$, which is used to convert a cost in bits to a cost in distortion terms, is calculated as: $\lambda=qpFactor \times 2^{qp+6*(bitDepthLuma-8)-12}$, where $qp$ is the slice QP and $qpFactor$ is calculated as follows: \begin{tabular}{lp{0.45\textwidth}} $= IQF$ & if $IQF >= 0$ and slice is a periodic intra slice \\ $= 0.57 \times \lambda_{scale}$ & if slice is a non-periodic intra slice \\ $=$ value from GOP table & otherwise \\ \end{tabular} where $IQF$ is the value specified using the IntraQPFactor option, and where $\lambda_{scale}$ is: \begin{tabular}{lp{0.45\textwidth}} $1$ & if LambdaFromQpEnable=true \\ $1.0 - max(0,min(0.5,0.05*B))$ & if LambdaFromQpEnable=false \\ \end{tabular} where $B$ is the number of B frames. If LambdaFromQpEnable=false, then the $\lambda$ is also subsequently scaled for non-top-level hiearchical depths, as follows: $\lambda = \lambda_{base} \times max(2, min(4, (sliceQP-12)/6))$ In addition, independent on the IntraQPFactor, if HadamardME=false, then for an inter slice the final $\lambda$ is scaled by a factor of $0.95$. \\ \Option{CbQpOffset (-cbqpofs)}% \Option{CrQpOffset (-crqpofs)} & %\ShortOption{-cbqpofs}% %\ShortOption{-crqpofs} & \Default{0}% \Default{0} & Global offset to apply to the luma QP to derive the QP of Cb and Cr respectively. These options correspond to the values of cb_qp_offset and cr_qp_offset, that are transmitted in the PPS. Valid values are in the range $[-12, 12]$. \\ \Option{LumaLevelToDeltaQPMode} & \Default{0} & Luma-level based Delta QP modulation. \par \begin{tabular}{cp{0.45\textwidth}} 0 & not used \\ 1 & Based on CTU average \\ 2 & Based on Max luma in CTU\\ \end{tabular} \\ \Option{LumaLevelToDeltaQPMaxValWeight} & \Default{1.0} & Weight of per block maximum luma value when LumaLevelToDeltaQPMode=2. \\ \Option{LumaLevelToDeltaQPMappingLuma} & \Default{\NotSet} & Specify luma values to use for the luma to delta QP mapping instead of using default values. Default values are: 0, 301, 367, 434, 501, 567, 634, 701, 767, 834. \\ \Option{LumaLevelToDeltaQPMappingDQP} & \Default{\NotSet} & Specify DQP values to use for the luma to delta QP mapping instead of using default values. Default values are: -3, -2, -1, 0, 1, 2, 3, 4, 5, 6. \\ \Option{WCGPPSEnable} & \Default{0} & Enable the WCG PPS modulation of the chroma QP, rather than the slice, which, unlike slice-level modulation, allows the deblocking process to consider the adjustment. To use, specify a fractional QP: the first part of the sequence will use $qpc=floor(QP)$ in the following calculation and PPS-0; the second part of the sequence will use $qpc=ceil(QP)$ and PPS-1. The $chromaQp$ that is then stored in the PPS is given as: $clip(round(WCGPPSXXQpScale*baseCQp)+XXQpOffset)$ where $baseCQp=(WCGPPSChromaQpScale*qpc+WCGPPSChromaQpOffset)$. Note that the slices will continue to have a delta QP applied. \\ \Option{WCGPPSChromaQpScale} & \Default{0.0} & Scale parameter for the linear chroma QP offset mapping used for WCG content. \\ \Option{WCGPPSChromaQpOffset} & \Default{0.0} & Offset parameter for the linear chroma QP offset mapping used for WCG content. \\ \Option{WCGPPSCbQpScale}% \Option{WCGPPSCrQpScale} & \Default{1.0} & Per chroma component QP scale factor depending on capture and representation color space. For Cb component with BT.2020 container use 1.14; for BT.709 material and 1.04 for P3 material. For Cr component with BT.2020 container use 1.79; for BT.709 material and 1.39 for P3 material. \\ \Option{SmoothQPReductionEnable} & \Default{0} & Enable QP reduction for smooth blocks according to a QP reduction model: $Clip3(SmoothQPReductionLimit, 0, SmoothQPReductionModelScale*QP+SmoothQPReductionModelOffset)$. The QP reduction model is used when SAD is less than SmoothQPReductionThreshold * number of samples in block. Where SAD is defined as the sum of absolute differences between original luma samples and luma samples predicted by a 2nd order polynomial model. The model parameters are determined by a least square fit to original luma samples on a granularity of 64x64 samples. \\ \Option{SmoothQPReductionThreshold} & \Default{3.0} & Threshold parameter for smoothness. \\ \Option{SmoothQPReductionModelScale} & \Default{-1.0} & Scale parameter of the QP reduction model. \\ \Option{SmoothQPReductionModelOffset} & \Default{27.0} & Offset parameter of the QP reduction model. \\ \Option{SmoothQPReductionLimit} & \Default{-16.0} & Threshold parameter for controlling amount of QP reduction by the QP reduction model. \\ \Option{SmoothQPReductionPeriodicity} & \Default{1} & Periodicity parameter for application of the QP reduction model. 1: all frames, 0: only intra pictures, 2: every second frame, etc. \\ \Option{BIM} & \Default{false} & Enable or disable Block Importance Mapping, QP adaptation depending on estimated propagation of reference samples. Depends on future and past reference frames configured for temporal filter. \\ \Option{SliceChromaQPOffsetPeriodicity} & \Default{0} & Defines the periodicity for inter slices that use the slice-level chroma QP offsets, as defined by SliceCbQpOffsetIntraOrPeriodic and SliceCrQpOffsetIntraOrPeriodic. A value of 0 disables the periodicity. It is intended to be used in low-delay configurations where an regular intra period is not defined. \\ \Option{SliceCbQpOffsetIntraOrPeriodic}% \Option{SliceCrQpOffsetIntraOrPeriodic} & \Default{0} & Defines the slice-level QP offset to be used for intra slices, or once every 'SliceChromaQPOffsetPeriodicity' pictures. \\ \Option{MaxCuDQPDepth (-dqd)} & %\ShortOption{\None} & \Default{0} & Defines maximum depth of a minimum CuDQP for sub-LCU-level delta QP. MaxCuDQPDepth shall be greater than or equal to SliceGranularity. \\ \Option{RDOQ} & %\ShortOption{\None} & \Default{true} & Enables or disables rate-distortion-optimized quantization for transformed TUs. \\ \Option{RDOQTS} & %\ShortOption{\None} & \Default{true} & Enables or disables rate-distortion-optimized quantization for transform-skipped TUs. \\ \Option{SelectiveRDOQ} & %\ShortOption{\None} & \Default{false} & Enables or disables selective rate-distortion-optimized quantization. A simple quantization is use to pre-analyze, whether to bypass the RDOQ process or not. If all the coefficients are quantized to 0, the RDOQ process is bypassed. Otherwise, the RDOQ process is performed as usual. \\ \Option{DeltaQpRD (-dqr)} & %\ShortOption{-dqr} & \Default{0} & Specifies the maximum QP offset at slice level for multi-pass slice encoding. When encoding, each slice is tested multiple times by using slice QP values in the range $[-\mathrm{DeltaQpRD}, \mathrm{DeptaQpRD}]$, and the best QP value is chosen as the slice QP. \\ \Option{MaxDeltaQP (-d)} & %\ShortOption{-d} & \Default{0} & Specifies the maximum QP offset at the largest coding unit level for the block-level adaptive QP assignment scheme. In the encoder, each largest coding unit is tested multiple times by using the QP values in the range $[-\mathrm{MaxDeltaQP}, \mathrm{MaxDeltaQP}]$, and the best QP value is chosen as the QP value of the largest coding unit. \\ \Option{dQPFile (-m)} & %\ShortOption{-m} & \Default{\NotSet} & Specifies a file containing a list of QP deltas. The $n$-th line (where $n$ is 0 for the first line) of this file corresponds to the QP value delta for the picture with POC value $n$. \\ \Option{AdaptiveQp (-aq)} & %\ShortOption{-aq} & \Default{false} & Enable or disable QP adaptation based upon a psycho-visual model. \\ \Option{MaxQPAdaptationRange (-aqr)} & %\ShortOption{-aqps} & \Default{6} & Specifies the maximum QP adaptation range. \\ \Option{AdaptiveQpSelection (-aqps)} & %\ShortOption{-aqps} & \Default{false} & Specifies whether QP values for non-I frames will be calculated on the fly based on statistics of previously coded frames. \\ \Option{RecalculateQP...} \Option{AccordingToLambda} & %\ShortOption{\None} & \Default{false} & Recalculate QP values according to lambda values. Do not suggest to be enabled in all intra case. \\ \Option{ScalingList} & %\ShortOption{\None} & \Default{0} & Controls the specification of scaling lists: \par \begin{tabular}{cp{0.45\textwidth}} 0 & Scaling lists are disabled \\ 1 & Use default scaling lists \\ 2 & Scaling lists are specified in the file indicated by ScalingListFile \\ \end{tabular} \\ \Option{ScalingListFile} & %\ShortOption{\None} & \Default{\NotSet} & When ScalingList is set to 2, this parameter indicates the name of the file, which contains the defined scaling lists. If ScalingList is set to 2 and this parameter is an empty string, information on the format of the scaling list file is output and the encoder stops. \\ \Option{MaxCUChromaQpAdjustmentDepth} & %\ShortOption{\None} & \Default{-1} & Specifies the maximum depth for CU chroma QP adjustment; if negative, CU chroma QP adjustment is disabled. \\ \end{OptionTableNoShorthand} %% %% Slice coding parameters %% \begin{OptionTableNoShorthand}{Slice coding parameters}{tab:slice-coding} %\Option{SliceGranularity} & %\ShortOption{\None} & %\Default{0} & %Determines the depth in an LCU at which slices may begin and end. %\par %\begin{tabular}{cp{0.45\textwidth}} % 0 & Slice addresses are LCU aligned \\ % $1 \leq n \leq 3$ % & Slice start addresses are aligned to CUs at depth $n$ \\ %\end{tabular} % %Note: The smallest permissible alignment is 16x16 CUs. %Values of $n$ must satisfy this constraint, for example, with a 64x64 %LCU, $n$ must be less than or equal to 2. %\\ \Option{SliceMode} & %\ShortOption{\None} & \Default{0} & Controls the slice partitioning method in conjunction with SliceArgument. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Single slice \\ 1 & Maximum number of CTUs per slice \\ 2 & Maximum number of bytes per slice \\ 3 & Maximum number of tiles per slice \\ \end{tabular} \\ \Option{SliceArgument} & %\ShortOption{\None} & \Default{\NotSet} & Specifies the maximum number of CTUs, bytes or tiles in a slice depending on the SliceMode setting. \\ \Option{SliceSegmentMode} & %\ShortOption{\None} & \Default{0} & Enables (dependent) slice segment coding in conjunction with SliceSegmentArgument. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Single slice \\ 1 & Maximum number of CTUs per slice segment\\ 2 & Maximum number of bytes per slice segment\\ 3 & Maximum number of tiles per slice segment\\ \end{tabular} \\ \Option{SliceSegmentArgument} & %\ShortOption{\None} & \Default{\NotSet} & Defines the maximum number of CTUs, bytes or tiles a slice segment depending on the SliceSegmentMode setting. \\ \Option{WaveFrontSynchro} & %\ShortOption{\None} & \Default{false} & Enables the use of specific CABAC probabilities synchronization at the beginning of each line of CTBs in order to produce a bitstream that can be encoded or decoded using one or more cores. \\ \Option{TileUniformSpacing} & %\ShortOption{\None} & \Default{false} & Controls the mode used to determine per row and column tile sizes. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Each tile column width and tile row height is explicitly set by TileColumnWidthArray and TileRowHeightArray respectively \\ 1 & Tile columns and tile rows are uniformly spaced. \\ \end{tabular} \\ \Option{NumTileColumnsMinus1}% \Option{NumTileRowsMinus1} & %\ShortOption{\None} & \Default{0} & Specifies the tile based picture partitioning geometry as $\mathrm{NumTileColumnsMinus1} + 1 \times \mathrm{NumTileRowsMinus1} + 1$ columns and rows. \\ \Option{TileColumnWidthArray}% \Option{TileRowHeightArray} & %\ShortOption{\None} & \Default{\NotSet} & Specifies a space or comma separated list of widths and heights, respectively, of each tile column or tile row. The first value in the list corresponds to the leftmost tile column or topmost tile row. \\ \end{OptionTableNoShorthand} %% %% Deblocking filter parameters %% \begin{OptionTableNoShorthand}{Deblocking filter parameters}{tab:deblocking-filter} \Option{LoopFilterDisable} & %\ShortOption{\None} & \Default{false} & Enables or disables the in-loop deblocking filter. \\ \Option{LFCrossSliceBoundaryFlag} & %\ShortOption{\None} & \Default{true} & Enables or disables the use of in-loop filtering across slice boundaries. \\ \Option{LoopFilterOffsetInPPS}& %\ShortOption{\None}& \Default{false}& If enabled, the in-loop deblocking filter control parameters are sent in PPS. Otherwise, the in-loop deblocking filter control parameters are sent in the slice segment header. If deblocking filter parameters are sent in PPS, the same values of deblocking filter parameters are used for all pictures in the sequence (i.e. deblocking parameter = base parameter value). If deblocking filter parameters are sent in the slice segment header, varying deblocking filter parameters can be specified by setting parameters tcOffsetDiv2 and betaOffsetDiv2 in the GOP structure table. In this case, the final value of the deblocking filter parameter sent for a certain GOP picture is equal to (base parameter + GOP parameter for this picture). Intra-pictures use the base parameters values. \\ \Option{LoopFilterTcOffset_div2}& %\ShortOption{\None}& \Default{0}& Specifies the base value for the in-loop deblocking filter parameter tc_offset_div2. The final value of tc_offset_div2 shall be an integer number in the range $-6..6$. \\ \Option{LoopFilterBetaOffset_div2}& %\ShortOption{\None}& \Default{0}& Specifies the base value for the in-loop deblocking filter parameter beta_offset_div2. The final value of beta_offset_div2 shall be an integer number in the range $-6..6$. \\ \Option{DeblockingFilterMetric}& %\ShortOption{\None}& \Default{0}& Specifies the use of a deblocking filter metric to evaluate the suitability of deblocking. If non-zero then LoopFilterOffsetInPPS and LoopFilterDisable must be 0. Currently excepted values are 0, 1 and 2. \\ \Option{LFCrossSliceBoundaryFlag}& %\ShortOption{\None}& \Default{true}& Enables or disables the use of a deblocking across tile boundaries. \\ \end{OptionTableNoShorthand} %% %% Coding tools parameters %% \begin{OptionTableNoShorthand}{Coding tools parameters}{tab:coding-tools} \Option{AMP} & %\ShortOption{\None} & \Default{true} & Enables or disables the use of asymmetric motion partitions. \\ \Option{SAO} & %\ShortOption{\None} & \Default{true} & Enables or disables the sample adaptive offset (SAO) filter. \\ \Option{TestSAODisableAtPictureLevel} & %\ShortOption{\None} & \Default{false} & Enables the testing of disabling SAO at the picture level after having analysed all blocks. \\ \Option{SaoEncodingRate} & %\ShortOption{\None} & \Default{0.75} & When >0 SAO early picture termination is enabled for luma and chroma. \\ \Option{SaoEncodingRateChroma} & %\ShortOption{\None} & \Default{0.5} & The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma. \\ \Option{SAOLcuBoundary} & %\ShortOption{\None} & \Default{false} & Enables or disables SAO parameter estimation using non-deblocked pixels for LCU bottom and right boundary areas. \\ \Option{ResetEncoderStateAfterIRAP} & %\ShortOption{\None} & \Default{true} & When true, resets the encoder's decisions after an IRAP (POC order) \\ \Option{ConstrainedIntraPred} & %\ShortOption{\None} & \Default{false} & Enables or disables constrained intra prediction. Constrained intra prediction only permits samples from intra blocks in the same slice as the current block to be used for intra prediction. \\ \Option{FastUDIUseMPMEnabled} & %\ShortOption{\None} & \Default{true} & If enabled, adapt intra direction search, accounting for MPM \\ \Option{FastMEForGenBLowDelayEnabled} & %\ShortOption{\None} & \Default{true} & If enabled use a fast ME for generalised B Low Delay slices \\ \Option{UseBLambdaForNonKeyLowDelayPictures} & %\ShortOption{\None} & \Default{true} & Enables use of B-Lambda for non-key low-delay pictures \\ \Option{TransquantBypassEnable} & %\ShortOption{\None} & \Default{false} & Enables or disables the ability to bypass the transform, quantization and filtering stages at CU level. This option corresponds to the value of transquant_bypass_enabled_flag that is transmitted in the PPS. See CUTransquantBypassFlagForce for further details. \\ \Option{CUTransquantBypassFlagForce} & %\ShortOption{\None} & \Default{0} & Controls the per CU transformation, quantization and filtering mode decision. This option controls the value of the per CU cu_transquant_bypass_flag. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Bypass is searched on a CU-by-CU basis and will be used if the cost is lower than not bypassing. \\ 1 & Bypass is forced for all CUs. \\ \end{tabular} This option has no effect if TransquantBypassEnable is disabled. \\ \Option{PCMEnabledFlag} & %\ShortOption{\None} & \Default{false} & Enables or disables the use of PCM. The encoder will use cost measures on a CU-by-CU basis to determine if PCM mode is to be applied. \\ \Option{PCMLog2MaxSize} & %\ShortOption{\None} & \Default{5 \\ ($= \mathrm{log}_2(32)$)} & Specifies log2 of the maximum PCM block size. When PCM is enabled, the PCM mode is available for 2Nx2N intra PUs smaller than or equal to the specified maximum PCM block size \\ \Option{PCMLog2MinSize} & %\ShortOption{\None} & \Default{3} & Specifies log2 of the minimum PCM block size. When PCM is enabled, the PCM mode is available for 2Nx2N intra PUs larger than or equal to the specified minimum PCM block size. \par When larger than PCMLog2MaxSize, PCM mode is not used. \\ \Option{PCMInputBitDepthFlag} & %\ShortOption{\None} & \Default{true} & If enabled specifies that PCM sample bit-depth is set equal to InputBitDepth. Otherwise, it specifies that PCM sample bit-depth is set equal to InternalBitDepth. \\ \Option{PCMFilterDisableFlag} & %\ShortOption{\None} & \Default{false} & If enabled specifies that loop-filtering on reconstructed samples of PCM blocks is skipped. Otherwise, it specifies that loop-filtering on reconstructed samples of PCM blocks is not skipped. % 0 = (loop-filtering is not skipped for PCM samples). \\ \Option{WeightedPredP (-wpP)} & %\ShortOption{-wpP} & \Default{false} & Enables the use of weighted prediction in P slices. \\ \Option{WeightedPredB (-wpB)} & %\ShortOption{-wpB} & \Default{false} & Enables the use of weighted prediction in B slices. \\ \Option{WPMethod (-wpM)} & %\ShortOption{\-wpM} & \Default{0} & Sets the Weighted Prediction method to be used. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Image DC based method with joint colour component decision. \\ 1 & Image DC based method with separate colour component decision. \\ 2 & DC + Histogram refinement method (no clipping). \\ 3 & DC + Histogram refinement method (with clipping). \\ 4 & DC + Dual Histogram refinement method (with clipping). \\ \end{tabular} \\ \Option{Log2ParallelMergeLevel} & %\ShortOption{\None} & \Default{2} & Defines the PPS-derived Log2ParMrgLevel variable. \\ \Option{SignHideFlag (-SBH)} & %\ShortOption{-SBH} & \Default{true} & If enabled specifies that for each 4x4 coefficient group for which the number of coefficients between the first nonzero coefficient and the last nonzero coefficient along the scanning line exceeds 4, the sign bit of the first nonzero coefficient will not be directly transmitted in the bitstream, but may be inferred from the parity of the sum of all nonzero coefficients in the current coefficient group. \\ \Option{StrongIntraSmoothing (-sis)} & %\ShortOption{-sis} & \Default{true} & If enabled specifies that for 32x32 intra prediction block, the intra smoothing when applied is either the 1:2:1 smoothing filter or a stronger bi-linear interpolation filter. Key reference sample values are tested and if the criteria is satisfied, the stronger intra smoothing filter is applied. If disabled, the intra smoothing filter when applied is the 1:2:1 smoothing filter. \\ \Option{TMVPMode} & %\ShortOption{\None} & \Default{1} & Controls the temporal motion vector prediction mode. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Disabled for all slices. \\ 1 & Enabled for all slices. \\ 2 & Disabled only for the first picture of each GOPSize. \\ \end{tabular} \\ \Option{TransformSkip} & %\ShortOption{\None} & \Default{false} & Enables or disables transform-skipping mode decision. \\ \Option{TransformSkipFast} & %\ShortOption{\None} & \Default{false} & Enables or disables reduced testing of the transform-skipping mode decision for chroma TUs. When enabled, no RDO search is performed for chroma TUs, instead they are transform-skipped if the four corresponding luma TUs are also skipped. \par This option has no effect if TransformSkip is disabled. \\ \end{OptionTableNoShorthand} %% %% GOP based termporal filter parameters %% \begin{OptionTableNoShorthand}{GOP based temporal filter parameters}{tab:gop-based-temporal-filter} \Option{TemporalFilter} & %\ShortOption{\None} & \Default{false} & Enable motion-compensated temporal pre-filter. When enabled, at least one of TemporalFilterPastRefs and TemporalFilterFutureRefs must be larger than 0. \\ \Option{TemporalFilterPastRefs} & %\ShortOption{\None} & \Default{4} & Number of past frames used by the temporal filter. \\ \Option{TemporalFilterFutureRefs} & %\ShortOption{\None} & \Default{4} & Number of future frames used by the temporal filter. This may be set to 0 to avoid using future frames. \\ \Option{FirstValidFrame} & %\ShortOption{\None} & \Default{0} & Index of first frame in video sequence that may be used by the temporal filter. If a negative value is given, the index defaults to the value of FrameSkip. \\ \Option{LastValidFrame} & %\ShortOption{\None} & \Default{MAX_INT} & Index of last frame in video sequence that may be used by the temporal filter. If a negative value is given, the index defaults to the value of FrameSkip + FramesToBeEncoded - 1. \\ \Option{TemporalFilterStrengthFrame*} & %\ShortOption{\None} & \Default{} & Strength for every * frame in GOP based temporal filter, where * is an integer. E.g. --TemporalFilterStrengthFrame8 0.95 will enable GOP based temporal filter at every 8th frame with strength 0.95. Longer intervals overrides shorter when there a multiple matches. \\ \end{OptionTableNoShorthand} %% %% Rate control parameters %% \begin{OptionTableNoShorthand}{Rate control parameters}{tab:rate-control} \Option{RateControl} & %\ShortOption{\None} & \Default{false} & Rate control: enables rate control or not. \\ \Option{TargetBitrate} & %\ShortOption{\None} & \Default{0} & Rate control: target bitrate, in bps. \\ \Option{KeepHierarchicalBit} & %\ShortOption{\None} & \Default{0} & Rate control: 0: equal bit allocation among pictures; 1: fix ratio hierarchical bit allocation; 2: adaptive hierarchical ratio bit allocation. It is suggested to enable hierarchical bit allocation for hierarchical-B coding structure. \\ \Option{LCULevelRateControl} & %\ShortOption{\None} & \Default{true} & Rate control: true: LCU level RC; false: picture level RC. \\ \Option{RCLCUSeparateModel} & %\ShortOption{\None} & \Default{true} & Rate control: use LCU level separate R-lambda model or not. When LCULevelRateControl is equal to false, this parameter is meaningless. \\ \Option{InitialQP} & %\ShortOption{\None} & \Default{0} & Rate control: initial QP value for the first picture. 0 to auto determine the initial QP value. \\ \Option{RCForceIntraQP} & %\ShortOption{\None} & \Default{false} & Rate control: force intra QP to be equal to initial QP or not. \\ \Option{RCCpbSaturation} & %\ShortOption{\None} & \Default{false} & Rate control: enable target bits saturation to avoid CPB overflow and underflow or not. \\ \Option{RCCpbSize} & %\ShortOption{\None} & \Default{0} & Rate control: CPB size, in bps. \\ \Option{RCInitialCpbFullness} & %\ShortOption{\None} & \Default{0.9} & Rate control: ratio of initial CPB fullness per CPB size. (InitalCpbFullness/CpbSize) RCInitialCpbFullness should be smaller than or equal to 1. \\ \end{OptionTableNoShorthand} %% %% VUI parameters %% \begin{OptionTableNoShorthand}{VUI parameters}{tab:VUI} \Option{VuiParametersPresent (-vui)} & \Default{false} & Enable generation of vui_parameters(). \\ \Option{AspectRatioInfoPresent} & \Default{false} & Signals whether aspect_ratio_idc is present. \\ \Option{AspectRatioIdc} & \Default{0} & aspect_ratio_idc \\ \Option{SarWidth} & \Default{0} & Specifies the horizontal size of the sample aspect ratio. \\ \Option{SarHeight} & \Default{0} & Specifies the vertical size of the sample aspect ratio. \\ \Option{OverscanInfoPresent} & \Default{false} & Signals whether overscan_info_present_flag is present. \\ \Option{OverscanAppropriate} & \Default{false} & Indicates whether cropped decoded pictures are suitable for display using overscan. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Indicates that the decoded pictures should not be displayed using overscan. \\ 1 & Indicates that the decoded pictures may be displayed using overscan. \\ \end{tabular} \\ \Option{VideoSignalTypePresent} & \Default{false} & Signals whether video_format, video_full_range_flag, and colour_description_present_flag are present. \\ \Option{VideoFormat} & \Default{5} & Indicates representation of pictures. \\ \Option{VideoFullRange} & \Default{false} & Indicates the black level and range of luma and chroma signals. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Indicates that the luma and chroma signals are to be scaled prior to display. \\ 1 & Indicates that the luma and chroma signals are not to be scaled prior to display. \\ \end{tabular} \\ \Option{ColourDescriptionPresent} & \Default{false} & Signals whether colour_primaries, transfer_characteristics and matrix_coefficients are present. \\ \Option{ColourPrimaries} & \Default{2} & Indicates chromaticity coordinates of the source primaries. \\ \Option{TransferCharateristics} & \Default{2} & Indicates the opto-electronic transfer characteristics of the source. \\ \Option{MatrixCoefficients} & \Default{2} & Describes the matrix coefficients used in deriving luma and chroma from RGB primaries. \\ \Option{ChromaLocInfoPresent} & \Default{false} & Signals whether chroma_sample_loc_type_top_field and chroma_sample_loc_type_bottom_field are present. \\ \Option{ChromaSampleLocTypeTopField} & \Default{0} & Specifies the location of chroma samples for top field. \\ \Option{ChromaSampleLocTypeBottomField} & \Default{0} & Specifies the location of chroma samples for bottom field. \\ \Option{NeutralChromaIndication} & \Default{false} & Indicates that the value of all decoded chroma samples is equal to 1<<(BitDepthCr-1). \\ \Option{DefaultDisplayWindowFlag} & \Default{flag} & Indicates the presence of the Default Window parameters. \par \begin{tabular}{cp{0.45\textwidth}} false & Disabled \\ true & Enabled \\ \end{tabular} \\ \Option{DefDispWinLeftOffset}% \Option{DefDispWinRightOffset}% \Option{DefDispWinTopOffset}% \Option{DefDispWinBottomOffset} & \Default{0} & Specifies the horizontal and vertical offset to be applied to the input video from the conformance window in luma samples. Must be a multiple of the chroma resolution (e.g. a multiple of two for 4:2:0). \\ \Option{FrameFieldInfoPresentFlag} & \Default{false} & Specificies the value of the VUI syntax element `frame_field_info_present_flag', which indicates that pic_struct and field coding related values are present in picture timing SEI messages. \\ \Option{PocProportionalToTimingFlag} & \Default{false} & Specificies the value of the VUI syntax element `vui_poc_proportional_to_timing_flag', which indicates that the POC value is proportional to the output time with respect to the first picture in the CVS. \\ \Option{NumTicksPocDiffOneMinus} & \Default{0} & Specificies the value of the VUI syntax element `vui_num_ticks_poc_diff_one_minus1', which specifies the number of clock ticks corresponding to a difference of picture order count values equal to 1, and is used only when PocProportionalToTimingFlag is true. \\ \Option{BitstreamRestriction} & \Default{false} & Signals whether bitstream restriction parameters are present. \\ \Option{TilesFixedStructure} & \Default{false} & Indicates that each active picture parameter set has the same values of the syntax elements related to tiles. \\ \Option{MotionVectorsOverPicBoundaries} & \Default{false} & Indicates that no samples outside the picture boundaries are used for inter prediction. \\ \Option{MaxBytesPerPicDenom} & \Default{2} & Indicates a number of bytes not exceeded by the sum of the sizes of the VCL NAL units associated with any coded picture. \\ \Option{MaxBitsPerMinCuDenom} & \Default{1} & Indicates an upper bound for the number of bits of coding_unit() data. \\ \Option{Log2MaxMvLengthHorizontal} & \Default{15} & Indicate the maximum absolute value of a decoded horizontal MV component in quarter-pel luma units. \\ \Option{Log2MaxMvLengthVertical} & \Default{15} & Indicate the maximum absolute value of a decoded vertical MV component in quarter-pel luma units. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Range Extensions (Version 2) tool parameters}{tab:rext-tools} \Option{CostMode} & \Default{lossy} & Specifies the cost mode to use. \par \begin{tabular}{lp{0.3\textwidth}} lossy & $cost=distortion+\lambda \times bits$ \\ sequence_level_lossless & $cost=distortion / \lambda + bits$. \\ lossless & As with sequence_level_lossless, but QP is also set to 0 (this will be deprecated in the future) \\ mixed_lossless_lossy & As with sequence_level_lossless, but QP'=4 is used for pre-estimates of transquant-bypass blocks \\ \end{tabular} \\ \Option{ExtendedPrecision} & \Default{false} & Specifies the use of extended_precision_processing flag. Note that unless the HIGH_BIT_DEPTH_SUPPORT macro in TypeDef.h is enabled, all internal bit depths must be 8 when the ExtendedPrecision setting is enabled. This setting is only valid for the 16-bit RExt profiles. \\ \Option{HighPrecisionPredictionWeighting} & \Default{false} & Specifies the value of high_precision_prediction_weighting_flag. This setting is only valid for the 16-bit or 4:4:4 RExt profiles. \\ \Option{CrossComponentPrediction} & \Default{false} & When true, specifies the use of the cross component prediction tool (4:4:4 processing only). Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{ReconBasedCrossCPredictionEstimate} & \Default{false} & If true, then when determining the alpha value for cross-component prediction, use the reconstructed residual rather than the pre-transform encoder-side residual \\ \Option{SaoLumaOffsetBitShift} \Option{SaoChromaOffsetBitShift}& \Default{0} \Default{0} & Specifies the shift to apply to the SAO parameters. If negative, an estimate will be calculated based upon the initial QP. Version 1 and some Version 2 (RExt) profiles require this to be 0. \\ \Option{TransformSkipLog2MaxSize} & \Default{2} & Specifies the maximum TU size for which transform-skip can be used; the minimum value is 2. Version 1 and some Version 2 (RExt) profiles require this to be 2. \\ \Option{ImplicitResidualDPCM} & \Default{false} & When true, specifies the use of the implicitly signalled residual RDPCM tool (for intra). Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{ExplicitResidualDPCM} & \Default{false} & When true, specifies the use of the explicitly signalled residual RDPCM tool (for intra-block-copy and inter). Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{ResidualRotation} & \Default{false} & When true, specifies the use of the residual rotation tool. Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{SingleSignificanceMapContext} & \Default{false} & When true, specifies the use of a single significance map context for transform-skipped and transquant-bypassed TUs. Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{GolombRiceParameterAdaptation} & \Default{false} & When true, enable the adaptation of the Golomb-Rice parameter over the course of each slice. Version 1 and some Version 2 (RExt) profiles require this to be false. \\ \Option{AlignCABACBeforeBypass} & \Default{false} & When true, align the CABAC engine to a defined fraction of a bit prior to coding bypass data (including sign bits) when coeff_abs_level_remaining syntax elements are present in the group. This must always be true for the high-throughput-RExt profile, and false otherwise. \\ \Option{IntraReferenceSmoothing} & \Default{true} & When true, enable intra reference smoothing, otherwise disable it. Version 1 and some Version 2 (RExt) profiles require this to be true. \\ \end{OptionTableNoShorthand} \subsection{Encoder SEI parameters} The table below lists the SEI messages defined for Version 1 and Range-Extensions, and if available, the respective table that lists the controls within the HM Encoder to include the messages within the bit stream. \begin{SEIListTable}{List of Version 1 and RExt SEI messages} 0 & Buffering period & Table \ref{tab:sei-buffering-period} \\ 1 & Picture timing & Table \ref{tab:sei-picture-timing} \\ 2 & Pan-scan rectangle & (Not handled)\\ 3 & Filler payload & (Not handled)\\ 4 & User data registered by Rec. ITU-T T.35 & (Not handled)\\ 5 & User data unregistered & Decoded only\\ 6 & Recovery point & Table \ref{tab:sei-recovery-point} \\ 9 & Scene information & (Not handled)\\ 15 & Picture snapshot & (Not handled)\\ 16 & Progressive refinement segment start & (Not handled)\\ 17 & Progressive refinement segment end & (Not handled)\\ 19 & Film grain characteristics & Table \ref{tab:sei-film-grain} \\ 22 & Post-filter hint & (Not handled)\\ 23 & Tone mapping information & Table \ref{tab:sei-tone-mapping-info} \\ 45 & Frame packing arrangement & Table \ref{tab:sei-frame-packing-arrangement} \\ 47 & Display orientation & Table \ref{tab:sei-display-orientation} \\ 56 & Green Metadata & Table \ref{tab:sei-green-metadata} \\ 128 & Structure of pictures information & Table \ref{tab:sei-sop-info} \\ 129 & Active parameter sets & Table \ref{tab:sei-active-parameter-sets} \\ 130 & Decoding unit information & Table \ref{tab:sei-decoding-unit-info} \\ 131 & Temporal sub-layer zero index & Table \ref{tab:sei-temporal-level-0} \\ 132 & Decoded picture hash & Table \ref{tab:sei-decoded-picture-hash} \\ 133 & Scalable nesting & Table \ref{tab:sei-scalable-nesting} \\ 134 & Region refresh information & Table \ref{tab:sei-region-refresh-info} \\ 135 & No display & Table \ref{tab:sei-no-display} \\ 136 & Time code & Table \ref{tab:sei-time-code} \\ 137 & Mastering display colour volume & Table \ref{tab:sei-mastering-display-colour-volume} \\ 138 & Segmented rectangular frame packing arrangement & Table \ref{tab:sei-seg-rect-fpa}\\ 139 & Temporal motion-constrained tile sets & Table \ref{tab:sei-tmcts} \\ 140 & Chroma resampling filter hint & Table \ref{tab:chroma-resampling-filter-hint} \\ 141 & Knee function information & Table \ref{tab:sei-knee-function} \\ 142 & Colour remapping information & Table \ref{tab:sei-colour-remapping}\\ 143 & Deinterlaced field identification & (Not handled)\\ 144 & Content light level info & Table \ref{tab:sei-content-light-level}\\ 147 & Alternative transfer characteristics & Table \ref{tab:sei-alternative-transfer-characteristics}\\ 148 & Ambient viewing environment & Table \ref{tab:sei-ambient-viewing-environment}\\ 149 & Content colour volume & Table \ref{tab:sei-content-colour-volume}\\ 150 & Equirectangular projection & Table \ref{tab:sei-erp} \\ 151 & Cubemap projection & Table \ref{tab:sei-cmp} \\ 154 & Sphere rotation & Table \ref{tab:sei-sphere-rotation} \\ 155 & Region-wise packing & Table \ref{tab:sei-rwp} \\ 156 & Omni viewport & Table \ref{tab:sei-omni-viewport} \\ 158 & Motion-constrained tile set extraction information & Table \ref{tab:sei-mcts-extract} \\ 200 & SEI manifest & Table \ref{tab:sei-sei-manifest} \\ 201 & SEI prefix indication & Table \ref{tab:sei-sei-prefix-indication} \\ 203 & Shutter interval information & Table \ref{tab:sei-sii}\\ \end{SEIListTable} %% %% SEI messages %% \begin{OptionTableNoShorthand}{Buffering period SEI message encoder parameters}{tab:sei-buffering-period} \Option{SEIBufferingPeriod} & \Default{0} & Enables or disables the insertion of the Buffering period SEI messages. This option has no effect if VuiParametersPresent is disabled. SEIBufferingPeriod requires SEIActiveParameterSets to be enabled. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Picture timing SEI message encoder parameters}{tab:sei-picture-timing} \Option{SEIPictureTiming} & \Default{0} & Enables or disables the insertion of the Picture timing SEI messages. This option has no effect if VuiParametersPresent is disabled. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Recovery point SEI message encoder parameters}{tab:sei-recovery-point} \Option{SEIRecoveryPoint} & \Default{0} & Enables or disables the insertion of the Recovery point SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Film grain characteristics SEI message encoder parameters}{tab:sei-film-grain} \Option{SEIFGCEnabled} & \Default{0} & Enables or disables the insertion of the film grain characteristics SEI message. \\ \Option{SEIFGCAnalysisEnabled} & \Default{0} & Enable film grain analysis to estimate film grain parameters. \\ \Option{SEIFGCExternalMask} & \Default{\NotSet} & Read external file with mask for film grain analysis. If empty string, use internally calculated mask. \\ \Option{SEIFGCExternalDenoised} & \Default{\NotSet} & Read external file with denoised sequence for film grain analysis. If empty string, use MCTF for denoising. \\ \Option{SEIFGCCancelFlag} & \Default{0} & Specifies the persistence of any previous film grain characteristics SEI message in output order. For SMPTE-RDD5, the value must be 0. \\ \Option{SEIFGCPersistenceFlag} & \Default{0} & Specifies the persistence of the film grain characteristics SEI message for the current layer. For SMPTE-RDD5, the value must be 0; set to 1 when FGC SEI frequency is once per I-period \\ \Option{SEIFGCPerPictureSEI} & \Default{0} & Specifies the frequency of inserting the film grain characteristics SEI message. 0: FGC SEI is inserted once per I-period; 1: FGC SEI is inserted once per picture. \\ \Option{SEIFGCModelID} & \Default{0} & Specifies the film grain simulation model. For SMPTE-RDD5, the value must be 0. \par \begin{tabular}{cp{0.35\textwidth}} 0 & frequency filtering \\ 1 & auto-regression \\ \end{tabular} \\ \Option{SEIFGCSepColourDescPresentFlag} & \Default{0} & Specifies the presence of a distinct colour space description for the film grain characteristics specified in the SEI message. For SMPTE-RDD5, the value must be 0. \\ \Option{SEIFGCBlendingModeID} & \Default{0} & Specifies the blending mode used to blend the simulated film grain with the decoded images. For SMPTE-RDD5, the value must be 0. \par \begin{tabular}{cp{0.35\textwidth}} 0 & additive \\ 1 & multiplicative \\ \end{tabular} \\ \Option{SEIFGCLog2ScaleFactor} & \Default{2} & Specifies a scale factor used in the film grain characterization equations. \\ \Option{SEIFGCCompModelPresentComp0} & \Default{0} & Specifies the presence of film grain modelling on colour component 0. \\ \Option{SEIFGCCompModelPresentComp1} & \Default{0} & Specifies the presence of film grain modelling on colour component 1. \\ \Option{SEIFGCCompModelPresentComp2} & \Default{0} & Specifies the presence of film grain modelling on colour component 2. \\ \Option{SEIFGCNumIntensityIntervalMinus1Comp0} & \Default{0} & Specifies the number of intensity intervals minus 1 for comp 0 \\ \Option{SEIFGCNumIntensityIntervalMinus1Comp1} & \Default{0} & Specifies the number of intensity intervals minus 1 for comp 1 \\ \Option{SEIFGCNumIntensityIntervalMinus1Comp2} & \Default{0} & Specifies the number of intensity intervals minus 1 for comp 2 \\ \Option{SEIFGCNumModelValuesMinus1Comp0} & \Default{0} & Specifies the number of model values minus 1 for comp 0 \\ \Option{SEIFGCNumModelValuesMinus1Comp1} & \Default{0} & Specifies the number of model values minus 1 for comp 1 \\ \Option{SEIFGCNumModelValuesMinus1Comp2} & \Default{0} & Specifies the number of model values minus 1 for comp 2 \\ \Option{SEIFGCIntensityIntervalLowerBoundComp0} & \Default{0} & Specifies the lower bound of intensity interval for comp 0 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCIntensityIntervalLowerBoundComp1} & \Default{0} & Specifies the lower bound of intensity interval for comp 1 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCIntensityIntervalLowerBoundComp2} & \Default{0} & Specifies the lower bound of intensity interval for comp 2 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCIntensityIntervalUpperBoundComp0} & \Default{0} & Specifies the upper bound of intensity interval for comp 0 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCIntensityIntervalUpperBoundComp1} & \Default{0} & Specifies the upper bound of intensity interval for comp 1 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCIntensityIntervalUpperBoundComp2} & \Default{0} & Specifies the upper bound of intensity interval for comp 2 (for SMPTE-RDD5, non-overlapping interval) \\ \Option{SEIFGCCompModelValuesComp0} & \Default{0} & Specifies the model values for each intensity interval for comp 0 (sigma, h, v (h,v might be inferred based on number of model value)) \\ \Option{SEIFGCCompModelValuesComp1} & \Default{0} & Specifies the model values for each intensity interval for comp 1 (sigma, h, v (h,v might be inferred based on number of model value)) \\ \Option{SEIFGCCompModelValuesComp2} & \Default{0} & Specifies the model values for each intensity interval for comp 2 (sigma, h, v (h,v might be inferred based on number of model value)) \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Tone mapping information SEI message encoder parameters}{tab:sei-tone-mapping-info} \Option{SEIToneMappingInfo} & \Default{0} & Enables or disables the insertion of the Tone Mapping SEI message. \\ \Option{SEIToneMapId} & \Default{0} & Specifies Id of Tone Mapping SEI message for a given session. \\ \Option{SEIToneMapCancelFlag} & \Default{false} & Indicates that Tone Mapping SEI message cancels the persistance or follows. \\ \Option{SEIToneMapPersistenceFlag} & \Default{true} & Specifies the persistence of the Tone Mapping SEI message. \\ \Option{SEIToneMapCodedDataBitDepth} & \Default{8} & Specifies Coded Data BitDepth of Tone Mapping SEI messages. \\ \Option{SEIToneMapTargetBitDepth} & \Default{8} & Specifies Output BitDepth of Tome mapping function. \\ \Option{SEIToneMapModelId} & \Default{0} & Specifies Model utilized for mapping coded data into target_bit_depth range. \par \begin{tabular}{cp{0.35\textwidth}} 0 & linear mapping with clipping \\ 1 & sigmoidal mapping \\ 2 & user-defined table mapping \\ 3 & piece-wise linear mapping \\ 4 & luminance dynamic range mapping \\ \end{tabular} \\ \Option{SEIToneMapMinValue} & \Default{0} & Specifies the minimum value in mode 0. \\ \Option{SEIToneMapMaxValue} & \Default{1023} & Specifies the maxmum value in mode 0. \\ \Option{SEIToneMapSigmoidMidpoint} & \Default{512} & Specifies the centre point in mode 1. \\ \Option{SEIToneMapSigmoidWidth} & \Default{960} & Specifies the distance between 5% and 95% values of the target_bit_depth in mode 1. \\ \Option{SEIToneMapStartOfCodedInterval} & \Default{\None} & Array of user-defined mapping table. Default table can be set to the following: \par \begin{tabular}{cp{0.35\textwidth}} 0 12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 \\ 192 192 196 204 208 216 220 228 232 240 248 252 260 264 \\ 272 276 284 292 292 296 300 304 308 312 320 324 328 332 \\ 336 344 348 352 356 360 368 372 376 380 384 388 396 400 \\ 404 408 412 420 424 428 432 436 444 444 444 448 452 456 \\ 460 464 468 472 476 476 480 484 488 492 496 500 504 508 \\ 508 512 516 520 524 528 532 536 540 540 544 548 552 556 \\ 560 564 568 572 572 576 580 584 588 592 596 600 604 604 \\ 608 612 616 620 624 628 632 636 636 640 644 648 652 656 \\ 660 664 668 672 672 672 676 680 680 684 688 692 692 696 \\ 700 704 704 708 712 716 716 720 724 724 728 732 736 736 \\ 740 744 748 748 752 756 760 760 764 768 768 772 776 780 \\ 780 784 788 792 792 796 800 804 804 808 812 812 816 820 \\ 824 824 828 832 836 836 840 844 848 848 852 856 860 860 \\ 860 864 864 868 872 872 876 880 880 884 884 888 892 892 \\ 896 900 900 904 908 908 912 912 916 920 920 924 928 928 \\ 932 936 936 940 940 944 948 948 952 956 956 960 964 964 \\ 968 968 972 976 976 980 984 984 988 992 992 996 996 1000 \\ 1004 1004 1008 1012 1012 1016 1020 1024 \\ \end{tabular} \\ \Option{SEIToneMapNumPivots} & \Default{0} & Specifies the number of pivot points in mode 3. \\ \Option{SEIToneMapCodedPivotValue} & \Default{\None} & Array of coded pivot point in mode 3. A suggested table is: \par \begin{tabular}{cp{0.45\textwidth}} 64 128 256 512 768 \end{tabular} \\ \Option{SEIToneMapTargetPivotValue} & \Default{\None} & Array of target pivot point in mode 3. A suggested table is: \par \begin{tabular}{cp{0.45\textwidth}} 48 73 111 168 215 \end{tabular} \\ \Option{SEIToneMap...} \Option{CameraIsoSpeedIdc} & \Default{0} & Indicates the camera ISO speed for daylight illumination. \\ \Option{SEIToneMap...} \Option{CameraIsoSpeedValue} & \Default{400} & Specifies the camera ISO speed for daylight illumination of Extended_ISO. \\ \Option{SEIToneMap...} \Option{ExposureIndexIdc} & \Default{0} & Indicates the exposure index setting of the camera. \\ \Option{SEIToneMap...} \Option{ExposureIndexValue} & \Default{400} & Specifies the exposure index setting of the cameran of Extended_ISO. \\ \Option{SEIToneMapExposure...} \Option{CompensationValueSignFlag} & \Default{0} & Specifies the sign of ExposureCompensationValue. \\ \Option{SEIToneMapExposure...} \Option{CompensationValueNumerator} & \Default{0} & Specifies the numerator of ExposureCompensationValue. \\ \Option{SEIToneMapExposure...} \Option{CompensationValueDenomIdc} & \Default{2} & Specifies the denominator of ExposureCompensationValue. \\ \Option{SEIToneMapRef...} \Option{ScreenLuminanceWhite} & \Default{350} & Specifies reference screen brightness setting in units of candela per square metre. \\ \Option{SEIToneMapExtended...} \Option{RangeWhiteLevel} & \Default{800} & Indicates the luminance dynamic range. \\ \Option{SEIToneMapNominal...} \Option{BlackLevelLumaCodeValue} & \Default{16} & Specifies luma sample value of the nominal black level assigned decoded pictures. \\ \Option{SEIToneMapNominal...} \Option{WhiteLevelLumaCodeValue} & \Default{235} & Specifies luma sample value of the nominal white level assigned decoded pictures. \\ \Option{SEIToneMapExtended...} \Option{WhiteLevelLumaCodeValue} & \Default{300} & Specifies luma sample value of the extended dynamic range assigned decoded pictures. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Frame packing arrangement SEI message encoder parameters}{tab:sei-frame-packing-arrangement} \Option{SEIFramePacking} & \Default{0} & Enables or disables the insertion of the Frame packing arrangement SEI messages. \\ \Option{SEIFramePackingType} & \Default{0} & Indicates the arrangement type in the Frame packing arrangement SEI message. This option has no effect if SEIFramePacking is disabled. \par \begin{tabular}{cp{0.35\textwidth}} 3 & Side by Side \\ 4 & Top Bottom \\ 5 & Frame Alternate \\ \end{tabular} \\ \Option{SEIFramePackingInterpretation} & \Default{0} & Indicates the constituent frames relationship in the Frame packing arrangement SEI message. This option has no effect if SEIFramePacking is disabled. \par \begin{tabular}{cp{0.35\textwidth}} 0 & Unspecified \\ 1 & Frame 0 is associated with the left view of a stereo pair \\ 2 & Frame 0 is associated with the right view of a stereo pair \\ \end{tabular} \\ \Option{SEIFramePackingQuincunx} & \Default{0} & Enables or disables the quincunx_sampling signalling in the Frame packing arrangement SEI messages. This option has no effect if SEIFramePacking is disabled. \\ \Option{SEIFramePackingId} & \Default{0} & Indicates the session number in the Frame packing arrangement SEI messages. This option has no effect if SEIFramePacking is disabled. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Display orientation SEI message encoder parameters}{tab:sei-display-orientation} \Option{SEIDisplayOrientation} & \Default{0} & Enables or disables the insertion of the Display orientation SEI messages. \par \begin{tabular}{cp{0.20\textwidth}} 0 & Disabled \\ N: $0 < N < (2^{16} - 1)$ & Enable display orientation SEI message with \mbox{anticlockwise_rotation = N} and \mbox{display_orientation_repetition_period = 1} \\ \end{tabular} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Green Metadata SEI message encoder parameters}{tab:sei-green-metadata} \Option{SEIGreenMetadataType} & \Default{0} & Specifies the type of metadata that is present in the SEI message. \par \begin{tabular}{cp{0.35\textwidth}} 0 & Reserved \\ 1 & Metadata enabling quality recovery after low-power encoding is present \\ \end{tabular} \\ \Option{SEIXSDMetricType} & \Default{0} & Indicates the type of the objective quality metric. \par \begin{tabular}{cp{0.35\textwidth}} 0 & PSNR is used as objective quality metric \\ \end{tabular} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Structure of pictures information SEI message encoder parameters}{tab:sei-sop-info} \Option{SEISOPDescription} & \Default{0} & Enables or disables the insertion of the Structure of pictures information SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Active parameter sets SEI message encoder parameters}{tab:sei-active-parameter-sets} \Option{SEIActiveParameterSets} & \Default{0} & Enables or disables the insertion of the Active parameter sets SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Decoding unit information SEI message encoder parameters}{tab:sei-decoding-unit-info} \Option{SEIDecodingUnitInfo} & \Default{0} & Enables or disables the insertion of the Decoding unit information SEI messages. This option has no effect if VuiParametersPresent is disabled. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Temporal sub-layer zero index SEI message encoder parameters}{tab:sei-temporal-level-0} \Option{SEITemporalLevel0Index} & \Default{0} & Enables or disables the insertion of the Temporal level zero index SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Decoded picture hash SEI message encoder parameters}{tab:sei-decoded-picture-hash} \Option{SEIDecodedPictureHash} & \Default{0} & Enables or disables the calculation and insertion of the Decoded picture hash SEI messages. \par \begin{tabular}{cp{0.35\textwidth}} 0 & Disabled \\ 1 & Transmits MD5 in SEI message and writes the value to the encoder log \\ 2 & Transmits CRC in SEI message and writes the value to the encoder log \\ 3 & Transmits checksum in SEI message and writes the value to the encoder log \\ \end{tabular} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Scalable nesting SEI message encoder parameters}{tab:sei-scalable-nesting} \Option{SEIScalableNesting} & \Default{0} & Enables or disables the use of the scalable nesting SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Region refresh information SEI message encoder parameters}{tab:sei-region-refresh-info} \Option{SEIGradualDecodingRefreshInfo} & \Default{0} & Enables or disables the insertion of the Gradual decoding refresh information SEI messages. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{No display SEI message encoder parameters}{tab:sei-no-display} \Option{SEINoDisplay} & \Default{0} & When non-zero, generate no-display SEI message for temporal layer N or higher. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Time code SEI message encoder parameters}{tab:sei-time-code} \Option{SEITimeCodeEnabled} & \Default{false} & When true (non-zero), generate Time code SEI messages. \\ \Option{SEITimeCodeNumClockTs} & \Default{0} & Number of clock time sets, in the range of 0 to 3 (inclusive). \\ \Option{SEITimeCodeTimeStampFlag} & \Default{\None} & Time stamp flag associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeFieldBasedFlag} & \Default{\None} & Field based flag associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeCountingType} & \Default{\None} & Counting type associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeFullTsFlag} & \Default{\None} & Full time stamp flag associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeDiscontinuityFlag} & \Default{\None} & Discontinuity flag associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeCntDroppedFlag} & \Default{\None} & Counter dropped flag associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeNumFrames} & \Default{\None} & Number of frames associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeSecondsFlag} & \Default{\None} & Flag to signal seconds value presence in each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeMinutesFlag} & \Default{\None} & Flag to signal minutes value presence in each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeHoursFlag} & \Default{\None} & Flag to signal hours value presence in each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeSecondsValue} & \Default{\None} & Seconds value for each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeMinutesValue} & \Default{\None} & Minutes value for each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeHoursValue} & \Default{\None} & Hours value for each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeOffsetLength} & \Default{\None} & Time offset length associated to each time set (comma or space separated list of entries). \\ \Option{SEITimeCodeTimeOffset} & \Default{\None} & Time offset associated to each time set (comma or space separated list of entries). \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Mastering display colour volume SEI message encoder parameters}{tab:sei-mastering-display-colour-volume} \Option{SEIMasteringDisplayColourVolume} & \Default{false} & When true (non-zero), generate Mastering display colour volume SEI message. \\ \Option{SEIMasteringDisplayMaxLuminance} & \Default{10000} & Specifies the mastering display maximum luminance value in units of 1/10000 candela per square metre. \\ \Option{SEIMasteringDisplayMinLuminance} & \Default{0} & Specifies the mastering display minimum luminance value in units of 1/10000 candela per square metre. \\ \Option{SEIMasteringDisplayPrimaries} & \Default{0,50000, 0,0, 50000,0} & Mastering display primaries for all three colour planes in CIE xy coordinates in increments of 1/50000 (results in the ranges 0 to 50000 inclusive). \\ \Option{SEIMasteringDisplayWhitePoint} & \Default{16667, 16667} & Mastering display white point CIE xy coordinates in normalized increments of 1/50000 (e.g. 0.333 = 16667). \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Segmented rectangular frame packing arrangement SEI message encoder parameters}{tab:sei-seg-rect-fpa} \Option{SEISegmentedRectFramePacking} & \Default{0} & Controls generation of segmented rectangular frame packing SEI messages. \\ \Option{SEISegmentedRectFramePackingCancel} & \Default{false} & If true, cancels the persistence of any previous SRFPA SEI message. \\ \Option{SEISegmentedRectFramePackingType} & \Default{0} & Specifies the arrangement of the frames in the reconstructed picture. \\ \Option{SEISegmentedRectFramePackingPersistence} & \Default{false} & If false the SEI applies to the current frame only. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Temporal motion-constrained tile sets SEI message encoder parameters}{tab:sei-tmcts} \Option{SEITempMotionConstrainedTileSets} & \Default{false} & When true (non-zero), generates example temporal motion constrained tile sets SEI messages. \\ \Option{SEITMCTSTileConstraint} & \Default{false} & When true (non-zero), the following encoding settings are enabled: \begin{itemize} \item mc_all_tiles_exact_sample_value_match_flag and each_tile_one_tile_set_flag will be set equal to one int the temporal motion constrained tile sets SEI message \item Motion vectors are constrained to not cross tile boundaries \item TMVP and merge mode are constrained to not cross tile boundaries \item LFCrossTileBoundaryFlag will be disabled \end{itemize} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Chroma resampling filter hint SEI message encoder parameters}{tab:chroma-resampling-filter-hint} \Option{SEIChromaResamplingFilterHint} & \Default{false} & When true (non-zero), generates example chroma sampling filter hint SEI messages. \\ \Option{SEIChromaResamplingHorizontalFilterType} & \Default{2} & Defines the index of the chroma sampling horizontal filter: \par \begin{tabular}{cp{0.35\textwidth}} 0 & Unspecified \\ 1 & Filters signalled within the SEI message \\ 2 & Filters as described by SMPTE RP 2050-1:2012\\ \end{tabular} \\ \Option{SEIChromaResamplingVerticalFilterType} & \Default{2} & Defines the index of the chroma sampling vertical filter: \par \begin{tabular}{cp{0.35\textwidth}} 0 & Unspecified \\ 1 & Filters signalled within the SEI message \\ 2 & Filters as described in the 5/3 filter description of ITU-T Rec. T.800 | ISO/IEC 15444-1\\ \end{tabular} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Knee function SEI message encoder parameters}{tab:sei-knee-function} \Option{SEIKneeFunctionInfo} & \Default{false} & Enables (true) or disables (false) the insertion of the Knee function SEI messages. \\ \Option{SEIKneeFunctionId} & \Default{0} & Specifies Id of Knee function SEI message for a given session. \\ \Option{SEIKneeFunctionCancelFlag} & \Default{false} & Indicates that Knee function SEI message cancels the persistance (true) or follows (false). \\ \Option{SEIKneeFunctionPersistenceFlag} & \Default{true} & Specifies the persistence of the Knee function SEI message. \\ \Option{SEIKneeFunctionInputDrange} & \Default{1000} & Specifies the peak luminance level for the input picture of Knee function SEI messages. \\ \Option{SEIKneeFunctionInputDispLuminance} & \Default{100} & Specifies the expected display brightness for the input picture of Knee function SEI messages. \\ \Option{SEIKneeFunctionOutputDrange} & \Default{4000} & Specifies the peak luminance level for the output picture of Knee function SEI messages. \\ \Option{SEIKneeFunctionOutputDispLuminance} & \Default{800} & Specifies the expected display brightness for the output picture of Knee function SEI messages. \\ \Option{SEIKneeFunctionNumKneePointsMinus1} & \Default{2} & Specifies the number of knee points - 1. \\ \Option{SEIKneeFunctionInputKneePointValue} & \Default{} & Array of input knee point. Default table can be set to the following: \par \begin{tabular}{cp{0.45\textwidth}} 600 800 900 \end{tabular} \\ \Option{SEIKneeFunctionOutputKneePointValue} & \Default{} & Array of output knee point. Default table can be set to the following: \par \begin{tabular}{cp{0.45\textwidth}} 100 250 450 \end{tabular} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Colour remapping SEI message encoder parameters}{tab:sei-colour-remapping} \Option{SEIColourRemappingInfoFileRoot (-cri)} & \Default{\NotSet} & Specifies the prefix of input Colour Remapping Information file. Prefix is completed by ``_x.txt'' where x is the POC number. The contents of the file are a list of the SEI message's syntax element names (in decoding order) immediately followed by a `:' and then the associated value. An example file can be found in cfg/misc/example_colour_remapping_sei_encoder_0.txt. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Content light level info SEI message encoder parameters}{tab:sei-content-light-level} \Option{SEICLLEnabled} & \Default{false} & Enables or disables the insertion of the content light level SEI message. \\ \Option{SEICLLMaxContentLightLevel} & \Default{4000} & When not equal to 0, specifies an upper bound on the maximum light level among all individual samples in a 4:4:4 representation of red, green, and blue colour primary intensities in the linear light domain for the pictures of the CLVS, in units of candelas per square metre. When equal to 0, no such upper bound is indicated. \\ \Option{SEICLLMaxPicAvgLightLevel} & \Default{0} & When not equal to 0, specifies an upper bound on the maximum average light level among the samples in a 4:4:4 representation of red, green, and blue colour primary intensities in the linear light domain for any individual picture of the CLVS, in units of candelas per square metre. When equal to 0, no such upper bound is indicated. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Alternative transfer characteristics SEI message encoder parameters}{tab:sei-alternative-transfer-characteristics} \Option{SEIPreferredTransferCharacteristics} & \Default{18} & Indicates a preferred alternative value for the transfer_characteristics syntax element that is indicated by the colour description syntax of VUI parameters. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Ambient viewing environment SEI message encoder parameters}{tab:sei-ambient-viewing-environment} \Option{SEIAVEEnabled} & \Default{false} & Enables or disables the insertion of the ambient viewing environment SEI message. \\ \Option{SEIAVEAmbientIlluminance} & \Default{100000} & Specifies the environmental illuminance of the ambient viewing environment in units of 1/10000 lux. The value shall not be 0. \\ \Option{SEIAVEAmbientLightX} & \Default{15635} & Specifies the x chromaticity coordinate, according to the CIE 1931 definition, of the environmental ambient light in the nominal viewing environment in normalized increments of 1/50000. The value shall be in the range of 0 to 50,000, inclusive. \\ \Option{SEIAVEAmbientLightY} & \Default{16450} & Specifies the y chromaticity coordinate, according to the CIE 1931 definition, of the environmental ambient light in the nominal viewing environment in normalized increments of 1/50000. The value shall be in the range of 0 to 50,000, inclusive. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Content colour volume SEI message encoder parameters}{tab:sei-content-colour-volume} \Option{SEICCVEnabled} & \Default{false} & Enables or disables the insertion of the content colour volume SEI message. \\ \Option{SEICCVCancelFlag} & \Default{false} & Specifies the persistence of any previous content colour volume SEI message in output order. \\ \Option{SEICCVPersistenceFlag} & \Default{true} & Specifies the persistence of the content colour volume SEI message for the current layer. \\ \Option{SEICCVPrimariesPresent} & \Default{true} & Specifies whether the CCV primaries are present in the content colour volume SEI message. \\ \Option{m_ccvSEIPrimariesX0} & \Default{0.300} & Specifies the x coordinate, according to the CIE 1931 definition, of the first (green) colour primary component in normalized increments of 1/50000. \\ \Option{m_ccvSEIPrimariesY0} & \Default{0.600} & Specifies the y coordinate, according to the CIE 1931 definition, of the first (green) colour primary component in normalized increments of 1/50000. \\ \Option{m_ccvSEIPrimariesX1} & \Default{0.150} & Specifies the x coordinate, according to the CIE 1931 definition, of the second (blue) colour primary component in normalized increments of 1/50000. \\ \Option{m_ccvSEIPrimariesY1} & \Default{0.060} & Specifies the y coordinate, according to the CIE 1931 definition, of the second (blue) colour primary component in normalized increments of 1/50000. \\ \Option{m_ccvSEIPrimariesX2} & \Default{0.640} & Specifies the x coordinate, according to the CIE 1931 definition, of the third (red) colour primary component in normalized increments of 1/50000. \\ \Option{m_ccvSEIPrimariesY2} & \Default{0.330} & Specifies the y coordinate, according to the CIE 1931 definition, of the third (red) colour primary component in normalized increments of 1/50000. \\ \Option{SEICCVMinLuminanceValuePresent} & \Default{true} & Specifies whether the CCV min luminance value is present in the content colour volume SEI message. \\ \Option{SEICCVMinLuminanceValue} & \Default{0.0} & specifies the CCV min luminance value in the content colour volume SEI message. \\ \Option{SEICCVMaxLuminanceValuePresent} & \Default{1} & Specifies whether the CCV max luminance value is present in the content colour volume SEI message. \\ \Option{SEICCVMaxLuminanceValue} & \Default{0.1} & specifies the CCV max luminance value in the content colour volume SEI message. \\ \Option{SEICCVAvgLuminanceValuePresent} & \Default{1} & Specifies whether the CCV avg luminance value is present in the content colour volume SEI message. \\ \Option{SEICCVAvgLuminanceValue} & \Default{0.01} & specifies the CCV avg luminance value in the content colour volume SEI message. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Equirectangular Projection SEI message encoder parameters}{tab:sei-erp} \Option{SEIErpEnabled} & \Default{false} & Enables (true) or disables (false) the insertion of equirectangular projection SEI message. \\ \Option{SEIErpCancelFlag} & \Default{true} & Indicates that equirectangular projection SEI message cancels the persistence (true) or follows (false). \\ \Option{SEIErpPersistenceFlag} & \Default{false} & Specifies the persistence of the equirectangular projection SEI message. \\ \Option{SEIErpGuardBandFlag} & \Default{false} & Indicates the existence of guard band areas in the constituent picture. \\ \Option{SEIErpGuardBandType} & \Default{0} & Indicates the type of the guard bands. \\ \Option{SEIErpLeftGuardBandWidth} & \Default{0} & Inicates the width of the guard band on the left side of the onstituent picture. \\ \Option{SEIErpRightGuardBandWidth} & \Default{0} & Inicates the width of the guard band on the right side of the onstituent picture. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Cubemap Projection SEI message encoder parameters}{tab:sei-cmp} \Option{SEICmpEnabled} & \Default{false} & Enables (true) or disables (false) the insertion of cubemap projection SEI message. \\ \Option{SEICmpCancelFlag} & \Default{true} & Indicates that cubemap projection SEI message cancels the persistence (true) or follows (false). \\ \Option{SEICmpPersistenceFlag} & \Default{false} & Specifies the persistence of the Cubemap Projection SEI message. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Sphere Rotation SEI message encoder parameters}{tab:sei-sphere-rotation} \Option{SEISphereRotationEnabled} & \Default{false} & Enables (true) or disables (false) the insertion of sphere rotation SEI message. \\ \Option{SEISphereRotationCancelFlag} & \Default{true} & Indicates that the sphere rotation SEI message cancels the persistence (true) or follows (false). \\ \Option{SEISphereRotationPersistenceFlag} & \Default{false} & Specifies the persistence of the sphere rotation SEI message. \\ \Option{SEISphereRotationYawRotation} & \Default{0} & Specifies the value of the yaw rotation angle. \\ \Option{SEISphereRotationPitchRotation} & \Default{0} & Specifies the value of the pitch rotation angle. \\ \Option{SEISphereRotationRollRotation} & \Default{0} & Specifies the value of the roll rotation angle. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Region-wise packing SEI message encoder parameters}{tab:sei-rwp} \Option{SEIRwpEnabled} & \Default{false} & Enables (true) or disables (false) the insertion of region-wise packing SEI message. \\ \Option{SEIRwpCancelFlag} & \Default{true} & Indicates that RWP SEI message cancels the persistence (true) or follows (false). \\ \Option{SEIRwpPersistenceFlag} & \Default{false} & Specifies the persistence of the RWP SEI message. \\ \Option{SEIRwpConstituentPictureMatchingFlag} & \Default{false} & Specifies the RWP SEI message applies individually to each constituent picture (true) or to the projected picture (false). \\ \Option{SEIRwpNumPackedRegions} & \Default{0} & Specifies the number of packed regions when constituent picture matching flag is equal to 0. \\ \Option{SEIRwpProjPictureWidth} & \Default{0} & Specifies the width of the projected picture. \\ \Option{SEIRwpProjPictureHeight} & \Default{0} & Specifies the height of the projected picture. \\ \Option{SEIRwpPackedPictureWidth} & \Default{0} & Specifies the width of the packed picture. \\ \Option{SEIRwpPackedPictureHeight} & \Default{0} & Specifies the height of the packed picture. \\ \Option{SEIRwpTransformType} & \Default{} & An array that specifies the rotation and mirroring to be applied to the packed regions. \\ \Option{SEIRwpGuardBandFlag} & \Default{} & An array that specifies the existence of guard band in the packed regions. \\ \Option{SEIRwpProjRegionWidth} & \Default{} & An array that specifies the width of the projected regions. \\ \Option{SEIRwpProjRegionHeight} & \Default{} & An array that specifies the height of the projected regions. \\ \Option{SEIRwpGuardBandFlag} & \Default{} & An array that specifies the existence of guard band in the packed regions. \\ \Option{SEIRwpProjRegionTop} & \Default{} & An array that specifies the top sample row of the projected regions. \\ \Option{SEIRwpProjRegionLeft} & \Default{} & An array that specifies the left-most sample column of the projected regions. \\ \Option{SEIRwpPackedRegionWidth} & \Default{} & An array that specifies the width of the packed regions. \\ \Option{SEIRwpPackedRegionHeight} & \Default{} & An array that specifies the height of the packed regions. \\ \Option{SEIRwpPackedRegionTop} & \Default{} & An array that specifies the top luma sample row of the packed regions. \\ \Option{SEIRwpPackedRegionLeft} & \Default{} & An array that specifies the left-most luma sample column of the packed regions. \\ \Option{SEIRwpLeftGuardBandWidth} & \Default{} & An array that specifies the width of the guard band on the left side of the packed regions. \\ \Option{SEIRwpRightGuardBandWidth} & \Default{} & An array that specifies the width of the guard band on the right side of the packed regions. \\ \Option{SEIRwpTopGuardBandHeight} & \Default{} & An array that specifies the height of the guard band above the packed regions. \\ \Option{SEIRwpBottomGuardBandHeight} & \Default{} & An array that specifies the height of the guard band below the packed regions. \\ \Option{SEIRwpGuardBandNotUsedForPredFlag} & \Default{} & An array that specifies if the guard bands is used in the inter prediction process. \\ \Option{SEIRwpGuardBandType} & \Default{} & An array that specifies the type of the guard bands for the packed regions. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Omni Viewport SEI message encoder parameters}{tab:sei-omni-viewport} \Option{SEIOmniViewportEnabled} & \Default{false} & Enables (true) or disables (false) the insertion of omni viewport SEI message. \\ \Option{SEIOmniViewportId} & \Default{0} & Contains an identifying number that may be used to identify the purpose of the one or more recommended viewport regions. \\ \Option{SEIOmniViewportCancelFlag} & \Default{true} & Indicates that the omni viewport SEI message cancels the persistence (true) or follows (false). \\ \Option{SEIOmniViewportPersistenceFlag} & \Default{false} & Specifies the persistence of the omni viewport SEI message. \\ \Option{SEIOmniViewportCntMinus1} & \Default{0} & Specifies the number of recommended viewport regions minus 1. \\ \Option{SEIOmniViewportAzimuthCentre} & \Default{} & An array that indicates the centre of the i-th recommended viewport region. \\ \Option{SEIOmniViewportElevationCentre} & \Default{} & An array that indicates the centre of the i-th recommended viewport region. \\ \Option{SEIOmniViewportTiltCentre} & \Default{} & An array that indicates the tilt angle of the i-th recommended viewport region. \\ \Option{SEIOmniViewportHorRange} & \Default{} & An array that indicates the azimuth range of the i-th recommended viewport region. \\ \Option{SEIOmniViewportVerRange} & \Default{} & An array that indicates the elevation range of the i-th recommended viewport region. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Motion-constrained tile sets extraction information sets SEI message encoder parameters}{tab:sei-mcts-extract} \Option{SEIMctsExtractInfoSet} & \Default{false} & When true (non-zero), generates example motion-constrained tile sets extraction information sets SEI message. with the following settings: \begin{itemize} \item SliceMode will be set to 0 and SliceArgument will be set to 1 (Enforcing one slice per tile). \item Extraction Info will be generated applying to each individual MCTS in the bitstream. \end{itemize} \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{SEI manifest SEI message encoder parameters}{tab:sei-sei-manifest} \Option{SEISEIManifestEnabled} & \Default{false} & Enables (true) or disables (false) the SEI manifest SEI message. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{SEI prefix indication SEI message encoder parameters}{tab:sei-sei-prefix-indication} \Option{SEISEIPrefixIndicationEnabled} & \Default{false} & Enables (true) or disables (false) the SEI prefix indication SEI message. \\ \end{OptionTableNoShorthand} \begin{OptionTableNoShorthand}{Shutter interval info SEI message encoder parameters}{tab:sei-sii} \Option{SEIShutterIntervalEnabled} & \Default{false} & Enables or disables the insertion of the shutter interval info SEI message. \\ \Option{SEISiiNumUnitsInShutterInterval} & \Default{1080000} & Specifies the number of time units of a clock operating at the frequency sii_time_scale Hz that corresponds to one increment of an shutter clock tick counter. \\ \Option{SEISiiTimeScale} & \Default{27000000} & Specifies the number of time units that pass in one second. \\ \Option{SEISiiMaxSubLayersMinus1} & \Default{0} & The value plus 1 specifies the maximum number of temporal sub-layers that may be present in each CVS referring to the SPS. The value shall be in the range of 0 to 6. \\ \Option{SEISiiFixedShutterIntervalWithinCVSFlag} & \Default{true} & Specifies if shutter interval info is the same for all temporal sub-layers in the CVS. \\ \Option{SEIShutterIntervalPreFilename (-sii)} & %\ShortOption{-sii} & \Default{\NotSet} & Specifies the file name of pre-processed video with shutter interval info SEI message. If empty, not output video. \\ \end{OptionTableNoShorthand} %\Option{SEITimeCode} & %\Default{false} & %When true, generate time code SEI messages. %\\ %% %% %% \subsection{Hardcoded encoder parameters} \begin{MacroTable}{CommonDef.h constants} ADAPT_SR_SCALE & 1 & Defines a scaling factor used to derive the motion search range is adaptive (see ASR configuration parameter). Default value is 1. \\ MAX_GOP & 64 & maximum size of value of hierarchical GOP. \\ MAX_NUM_REF & 4 & maximum number of multiple reference frames \\ MAX_NUM_REF_LC & 8 & maximum number of combined reference frames \\ AMVP_MAX_NUM_CANDS & 2 & maximum number of final candidates \\ AMVP_MAX_NUM_CANDS_MEM & 3 & \\ MRG_MAX_NUM_CANDS & 5 & \\ DYN_REF_FREE & off & dynamic free of reference memories \\ MAX_TLAYER & 8 & maximum number of temporal layers \\ ADAPT_SR_SCALE & on & division factor for adaptive search range \\ EARLY_SKIP_THRES & 1.5 & early skip if RD < EARLY_SKIP_THRES*avg[BestSkipRD] \\ MAX_NUM_REF_PICS & 16 & \\ MAX_CHROMA_FORMAT_IDC & 3 & \\ \end{MacroTable} \subsubsection*{TypeDef.h} Numerous constants that guard individual adoptions are defined within \url{source/Lib/TLibCommon/TypeDef.h}. %% %% %% \clearpage \section{Using the decoder} \subsection{General} \begin{minted}{bash} TAppDecoder -b str.bin -o dec.yuv [options] \end{minted} \begin{OptionTableNoShorthand}{Decoder options}{tab:decoder-options} \Option{(--help)} & %\ShortOption{\None} & \Default{\None} & Prints usage information. \\ \Option{BitStreamFile (-b)} & %\ShortOption{-b} & \Default{\NotSet} & Defines the input bit stream file name. \\ \Option{ReconFile (-o)} & %\ShortOption{-o} & \Default{\NotSet} & Defines reconstructed YUV file name. If empty, no file is generated. \\ \Option{SkipFrames (-s)} & %\ShortOption{-s} & \Default{0} & Defines the number of pictures in decoding order to skip. \\ \Option{MaxTemporalLayer (-t)} & %\ShortOption{-t} & \Default{-1} & Defines the maximum temporal layer to be decoded. If -1, then all layers are decoded. \\ \Option{TarDecLayerIdSetFile (-l)} & %\ShortOption{-t} & \Default{\NotSet} & Specifies the targetDecLayerIdSet file name. The file would contain white-space separated LayerId values of the layers that are to be decoded. Omitting the parameter, or using a value of -1 in the file decodes all layers. \\ \Option{OutputBitDepth (-d)} & %\ShortOption{-d} & \Default{0 \\ (Native)} & Specifies the luma bit-depth of the reconstructed YUV file (the value 0 indicates that the native bit-depth is used) \\ \Option{OutputBitDepthC} & %\ShortOption{\None} & \Default{0 \\ (Native)} & Defines the chroma bit-depth of the reconstructed YUV file (the value 0 indicates that the native bit-depth is used) \\ \Option{SEIDecodedPictureHash} & %\ShortOption{\None} & \Default{1} & Enable or disable verification of any Picture hash SEI messages. When this parameter is set to 0, the feature is disabled and all messages are ignored. When set to 1 (default), the feature is enabled and the decoder has the following behaviour: \begin{itemize} \item If Picture hash SEI messages are included in the bit stream, the same type of hash is calculated for each decoded picture and written to the log together with an indication whether the calculted value matches the value in the SEI message. Decoding will continue even if there is a mismatch. \item After decoding is complete, if any MD5sum comparison failed, a warning is printed and the decoder exits with the status EXIT_FAILURE \item The per-picture MD5 log message has the following formats: [MD5:d41d8cd98f00b204e9800998ecf8427e,(OK)], [MD5:d41d8cd98f00b204e9800998ecf8427e,(unk)], [MD5:d41d8cd98f00b204e9800998ecf8427e,(***ERROR***)] [rxMD5:b9e1...] where, "(unk)" implies that no MD5 was signalled for this picture, "(OK)" implies that the decoder agrees with the signalled MD5, "(***ERROR***)" implies that the decoder disagrees with the signalled MD5. "[rxMD5:...]" is the signalled MD5 if different. \end{itemize} \\ \Option{OutputDecodedSEIMessagesFilename} & %\ShortOption{\None} & \Default{\NotSet} & When a non-empty file name is specified, information regarding any decoded SEI messages will be output to the indicated file. If the file name is '-', then stdout is used instead. \\ \Option{SEIColourRemappingInfoFilename} & %\ShortOption{\None} & \Default{\NotSet} & Specifies that the colour remapping SEI message should be applied to the output video, with the output written to this file. If no value is specified, the SEI message is ignored and no mapping is applied. \\ \Option{RespectDefDispWindow (-w)} & %\ShortOption{-w} & \Default{0} & Video region to be output by the decoder. \par \begin{tabular}{cp{0.45\textwidth}} 0 & Output content inside the conformance window. \\ 1 & Output content inside the default window. \\ \end{tabular} \\ \Option{OutputColourSpaceConvert} & \Default{\NotSet} & Specifies the colour space conversion to apply to 444 video. Permitted values are: \par \begin{tabular}{lp{0.45\textwidth}} UNCHANGED & No colour space conversion is applied \\ YCrCbToYCbCr & Swap the second and third components \\ GBRtoRGB & Reorder the three components \\ \end{tabular} If no value is specified, no colour space conversion is applied. The list may eventually also include RGB to YCbCr or YCgCo conversions.\\ \\ \Option{SEINoDisplay} & \Default{false} & When true, do not output frames for which there is an SEI NoDisplay message. \\ \Option{ClipOutputVideoToRec709Range} & %\ShortOption{\None} & \Default{0} & If 1 then clip output video to the Rec. 709 Range on saving when OutputBitDepth is less than InternalBitDepth. \\ \Option{TMCTSCheck} & %\ShortOption{\None} & \Default{0} & Enables checking of temporal motion constraints (Merge/TMVP, motion vectors) at tile boundaries. Checks are enabled, if \begin{itemize} \item a temporal motion constraint SEI is present in the bitstream \item the SEI message contains mc_all_tiles_exact_sample_value_match_flag and each_tile_one_tile_set_flag equal to 1 \item TMCTSCheck is equal to 1 \end{itemize} If violations are found, an error message is printed to stderr. \\ \end{OptionTableNoShorthand} \subsection{Using the decoder analyser} If the decoder is compiled with the macro RExt__DECODER_DEBUG_BIT_STATISTICS defined as 1 (either externally, or by editing TypeDef.h), the decoder will gather fractional bit counts associated with the different syntax elements, producing a table of the number of bits per syntax element, and where appropriate, according to block size and colour component/channel. The Linux makefile will compile both the analyser and standard version when the `all' or `everything' target is used (where the latter will also build high-bit-depth executables). %% %% %% \clearpage \section{Using additional tools} \subsection{MCTS extractor application} \subsubsection{General} \begin{minted}{bash} TAppMCTSExtractor -i str_in.bin -b str_in.bin [options] \end{minted} \begin{OptionTableNoShorthand}{MCTS Extractor options}{tab:mcts-extractor-options} \Option{(--help)} & %\ShortOption{\None} & \Default{\None} & Prints usage information. \\ \Option{InputBitstreamFile (-i)} & %\ShortOption{-i} & \Default{\NotSet} & Defines the input bitstream file name. \\ \Option{OutputBitstreamFile (-b)} & %\ShortOption{-b} & \Default{\NotSet} & Defines the output sub-bitstream file name. \\ \Option{TargetMCTSIdx (-d)} & %\ShortOption{-d} & \Default{0} & Target MCTS index to be extracted from input bitstream to output sub-bitstream. \\ \end{OptionTableNoShorthand} \subsubsection{Usage example} The MCTS extractor application allows extraction of MCTS sub-bitstreams from bitstreams containing the Temporal motion-constrained tile sets SEI message syntax and the Motion-constrained tile sets extraction information sets SEI message. In order to generate such a bitstream with TAppEncoder, the following parameters need to be set. \begin{verbatim} --SEITempMotionConstrainedTileSets=1 --SEITMCTSTileConstraint=1 --SEITMCTSExtractionInfo=1 \end{verbatim} \end{document} HM-HM-18.0/source/000077500000000000000000000000001442026013100135415ustar00rootroot00000000000000HM-HM-18.0/source/App/000077500000000000000000000000001442026013100142615ustar00rootroot00000000000000HM-HM-18.0/source/App/Parcat/000077500000000000000000000000001442026013100154735ustar00rootroot00000000000000HM-HM-18.0/source/App/Parcat/CMakeLists.txt000066400000000000000000000032141442026013100202330ustar00rootroot00000000000000# executable set( EXE_NAME parcat ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ) target_link_libraries( ${EXE_NAME} Threads::Threads ${ADDITIONAL_LIBS} ) # include the output directory, where the svnrevision.h file is generated include_directories(${CMAKE_CURRENT_BINARY_DIR}) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/parcat> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/parcat> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/parcat> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/parcat> $<$:${CMAKE_SOURCE_DIR}/bin/parcatStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/parcatStatic> $<$:${CMAKE_SOURCE_DIR}/bin/parcatStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/parcatStaticm> ) endif() # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/Parcat/parcat.cpp000066400000000000000000000255101442026013100174540ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #define PRINT_NALUS 0 enum NalUnitType { TRAIL_N = 0, // 0 TRAIL_R, // 1 TSA_N, // 2 TSA_R, // 3 STSA_N, // 4 STSA_R, // 5 RADL_N, // 6 RADL_R, // 7 RASL_N, // 8 RASL_R, // 9 RESERVED_VCL_N10, RESERVED_VCL_R11, RESERVED_VCL_N12, RESERVED_VCL_R13, RESERVED_VCL_N14, RESERVED_VCL_R15, BLA_W_LP, // 16 BLA_W_RADL, // 17 BLA_N_LP, // 18 IDR_W_RADL, // 19 IDR_N_LP, // 20 CRA, // 21 RESERVED_IRAP_VCL22, RESERVED_IRAP_VCL23, RESERVED_VCL24, RESERVED_VCL25, RESERVED_VCL26, RESERVED_VCL27, RESERVED_VCL28, RESERVED_VCL29, RESERVED_VCL30, RESERVED_VCL31, VPS, // 32 SPS, // 33 PPS, // 34 ACCESS_UNIT_DELIMITER, // 35 EOS, // 36 EOB, // 37 FILLER_DATA, // 38 PREFIX_SEI, // 39 SUFFIX_SEI, // 40 RESERVED_NVCL41, RESERVED_NVCL42, RESERVED_NVCL43, RESERVED_NVCL44, RESERVED_NVCL45, RESERVED_NVCL46, RESERVED_NVCL47, UNSPECIFIED_48, UNSPECIFIED_49, UNSPECIFIED_50, UNSPECIFIED_51, UNSPECIFIED_52, UNSPECIFIED_53, UNSPECIFIED_54, UNSPECIFIED_55, UNSPECIFIED_56, UNSPECIFIED_57, UNSPECIFIED_58, UNSPECIFIED_59, UNSPECIFIED_60, UNSPECIFIED_61, UNSPECIFIED_62, UNSPECIFIED_63, INVALID, }; /** Find the beginning and end of a NAL (Network Abstraction Layer) unit in a byte buffer containing H264 bitstream data. @param[in] buf the buffer @param[in] size the size of the buffer @param[out] nal_start the beginning offset of the nal @param[out] nal_end the end offset of the nal @return the length of the nal, or 0 if did not find start of nal, or -1 if did not find end of nal */ // DEPRECATED - this will be replaced by a similar function with a slightly different API int find_nal_unit(const uint8_t* buf, int size, int* nal_start, int* nal_end) { int i; // find start *nal_start = 0; *nal_end = 0; i = 0; while ( //( next_bits( 24 ) != 0x000001 && next_bits( 32 ) != 0x00000001 ) (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) && (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0 || buf[i+3] != 0x01) ) { i++; // skip leading zero if (i+4 >= size) { return 0; } // did not find nal start } if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) // ( next_bits( 24 ) != 0x000001 ) { i++; } if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) { /* error, should never happen */ return 0; } i+= 3; *nal_start = i; while (//( next_bits( 24 ) != 0x000000 && next_bits( 24 ) != 0x000001 ) i+3 < size && (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0) && (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0x01) ) { i++; // FIXME the next line fails when reading a nal that ends exactly at the end of the data } if (i+3 == size) { *nal_end = size; } else { *nal_end = i; } return (*nal_end - *nal_start); } const bool verbose = false; const char * NALU_TYPE[] = { "TRAIL_N", "TRAIL_R", "TSA_N", "TSA_R", "STSA_N", "STSA_R", "RADL_N", "RADL_R", "RASL_N", "RASL_R", "RSV_VCL_N10", "RSV_VCL_N12", "RSV_VCL_N14", "RSV_VCL_R11", "RSV_VCL_R13", "RSV_VCL_R15", "BLA_W_LP", "BLA_W_RADL", "BLA_N_LP", "IDR_W_RADL", "IDR_N_LP", "CRA_NUT", "RSV_IRAP_VCL22", "RSV_IRAP_VCL23", "unk", "unk", "unk", "unk", "unk", "unk", "unk", "unk", "VPS_NUT", "SPS_NUT", "PPS_NUT", "AUD_NUT", "EOS_NUT", "EOB_NUT", "FD_NUT", "PREFIX_SEI_NUT", "SUFFIX_SEI_NUT", }; int calc_poc(int iPOClsb, int prevTid0POC, int getBitsForPOC, int nalu_type) { int iPrevPOC = prevTid0POC; int iMaxPOClsb = 1<< getBitsForPOC; int iPrevPOClsb = iPrevPOC & (iMaxPOClsb - 1); int iPrevPOCmsb = iPrevPOC-iPrevPOClsb; int iPOCmsb; if( ( iPOClsb < iPrevPOClsb ) && ( ( iPrevPOClsb - iPOClsb ) >= ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb + iMaxPOClsb; } else if( (iPOClsb > iPrevPOClsb ) && ( (iPOClsb - iPrevPOClsb ) > ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb - iMaxPOClsb; } else { iPOCmsb = iPrevPOCmsb; } if ( nalu_type == BLA_W_LP || nalu_type == BLA_W_RADL || nalu_type == BLA_N_LP ) { // For BLA picture types, POCmsb is set to 0. iPOCmsb = 0; } return iPOCmsb + iPOClsb; } std::vector filter_segment(const std::vector & v, int idx, int * poc_base, int * last_idr_poc) { const uint8_t * p = v.data(); const uint8_t * buf = v.data(); int sz = (int) v.size(); int nal_start, nal_end; int off = 0; int cnt = 0; bool idr_found = false; std::vector out; out.reserve(v.size()); int bits_for_poc = 8; bool skip_next_sei = false; while(find_nal_unit(p, sz, &nal_start, &nal_end) > 0) { if(verbose) { printf( "!! Found NAL at offset %lld (0x%04llX), size %lld (0x%04llX) \n", (long long int)(off + (p - buf)), (long long int)(off + (p - buf)), (long long int)(nal_end - nal_start), (long long int)(nal_end - nal_start) ); } p += nal_start; std::vector nalu(p, p + nal_end - nal_start); int nalu_type = nalu[0] >> 1; int poc = -1; int poc_lsb = -1; int new_poc = -1; if(nalu_type == IDR_W_RADL || nalu_type == IDR_N_LP) { poc = 0; new_poc = *poc_base + poc; } if(nalu_type < 32 && nalu_type != IDR_W_RADL && nalu_type != IDR_N_LP) { int offset = 16; offset += 1; //first_slice_segment_in_pic_flag if (nalu_type >= BLA_W_LP && nalu_type <= RESERVED_IRAP_VCL23) { offset += 1; //no_output_of_prior_pics_flag } // determine offset for slice_pic_parameter_set_id TODO: ue(v) int byte_offset2 = offset / 8; int hi_bits2 = offset % 8; uint16_t data2 = (nalu[byte_offset2] << 8) | nalu[byte_offset2 + 1]; int low_bits2 = 16 - hi_bits2 - 1; if(((data2 >> low_bits2) % 2)) offset += 1; // PPSId=0 else offset += 3; // PPSId=1 offset += 1; // slice_type TODO: ue(v) // separate_colour_plane_flag is not supported in JEM1.0 if (nalu_type == CRA) { offset += 2; } int byte_offset = offset / 8; int hi_bits = offset % 8; uint16_t data = (nalu[byte_offset] << 8) | nalu[byte_offset + 1]; int low_bits = 16 - hi_bits - bits_for_poc; poc_lsb = (data >> low_bits) & 0xff; poc = poc_lsb; //calc_poc(poc_lsb, 0, bits_for_poc, nalu_type); new_poc = poc + *poc_base; // int picOrderCntLSB = (pcSlice->getPOC()-pcSlice->getLastIDR()+(1<getSPS()->getBitsForPOC())) & ((1<getSPS()->getBitsForPOC())-1); unsigned picOrderCntLSB = (new_poc - *last_idr_poc +(1 << bits_for_poc)) & ((1<> (16 - hi_bits); data = (hi << (16 - hi_bits)) | (picOrderCntLSB << low_bits) | low; nalu[byte_offset] = data >> 8; nalu[byte_offset + 1] = data & 0xff; ++cnt; } if(idx > 1 && (nalu_type == IDR_W_RADL || nalu_type == IDR_N_LP)) { skip_next_sei = true; idr_found = true; } if((idx > 1 && (nalu_type == IDR_W_RADL || nalu_type == IDR_N_LP )) || ((idx>1 && !idr_found) && ( nalu_type == VPS || nalu_type == SPS || nalu_type == PPS)) || (nalu_type == SUFFIX_SEI && skip_next_sei)) { } else { out.insert(out.end(), p - nal_start, p); out.insert(out.end(), nalu.begin(), nalu.end()); } if(nalu_type == SUFFIX_SEI && skip_next_sei) { skip_next_sei = false; } p += (nal_end - nal_start); sz -= nal_end; } *poc_base += cnt; return out; } std::vector process_segment(const char * path, int idx, int * poc_base, int * last_idr_poc) { FILE * fdi = fopen(path, "rb"); if (fdi == NULL) { fprintf(stderr, "Error: could not open input file: %s", path); exit(1); } fseek(fdi, 0, SEEK_END); size_t full_sz = ftell(fdi); fseek(fdi, 0, SEEK_SET); std::vector v(full_sz); size_t sz = fread((char*) v.data(), 1, full_sz, fdi); fclose(fdi); if(sz != full_sz) { fprintf(stderr, "Error: input file was not read completely."); exit(1); } return filter_segment(v, idx, poc_base, last_idr_poc); } int main(int argc, char * argv[]) { if(argc < 3) { printf("usage: %s [ ...] \n", argv[0]); return -1; } FILE * fdo = fopen(argv[argc - 1], "wb"); if (fdo==NULL) { fprintf(stderr, "Error: could not open output file: %s", argv[argc - 1]); exit(1); } int poc_base = 0; int last_idr_poc = 0; for(int i = 1; i < argc - 1; ++i) { std::vector v = process_segment(argv[i], i, &poc_base, &last_idr_poc); fwrite(v.data(), 1, v.size(), fdo); } fclose(fdo); } HM-HM-18.0/source/App/Parcat/readme.md000066400000000000000000000026671442026013100172650ustar00rootroot00000000000000 parcat - Concatenation tool for parallel simulations ==================================================== This tool allows to cat segments from parallel simulation according to JVET-B0036 into bitstream bitexact with corresponding output of sequential simulation. What it does ------------ This tool - removes any duplicated and unnecessary information from segments like SPS, PPS, VPS, IDR-frames, SEI from all segments but first. - adjust POC value to provide continuous numbering and correct referencing (actual POC modification occurs only for second and following segments) - cat filtered segments into single file Output of this tool is decodable HM bitstream. Usage ----- ``` parcat [ ... ] ``` where `` is result of parallel simulation according to JVET-B0036. Building -------- The tool is quite simple and is stored in one C++ file. You can build it using any decent C++98 compiler using command line. Alternatively cmake build system scripts are provided to maintain cross platform experience and simplify generation of IDE-s projects like Visual Studio. To use it - install cmake from [cmake.org](http://cmake.org) - create build folder inside project root folder (where CMakeLists.txt is located) - cd to this folder - configure project using following command line `cmake ..` - build project using your platform's default build system, say Visual Studio on Windows and make on UNIX HM-HM-18.0/source/App/SEIFilmGrainApp/000077500000000000000000000000001442026013100171335ustar00rootroot00000000000000HM-HM-18.0/source/App/SEIFilmGrainApp/CMakeLists.txt000066400000000000000000000041371442026013100217000ustar00rootroot00000000000000# executable set( EXE_NAME SEIFilmGrainApp ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ) # include the output directory, where the svnrevision.h file is generated include_directories(${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries( ${EXE_NAME} TLibCommon TLibDecoder TLibEncoder Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/SEIFilmGrainApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/SEIFilmGrainApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/SEIFilmGrainApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/SEIFilmGrainApp> $<$:${CMAKE_SOURCE_DIR}/bin/SEIFilmGrainAppStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/SEIFilmGrainAppStatic> $<$:${CMAKE_SOURCE_DIR}/bin/SEIFilmGrainAppStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/SEIFilmGrainAppStaticm> ) endif() # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/SEIFilmGrainApp/SEIFilmGrainApp.cpp000066400000000000000000000300451442026013100225130ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainApp.cpp \brief Decoder application class */ #include #include #include #include #include "SEIFilmGrainApp.h" #include "TLibDecoder/AnnexBread.h" #if JVET_X0048_X0103_FILM_GRAIN //! \ingroup SEIFilmGrainApp //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== SEIFilmGrainApp::SEIFilmGrainApp() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in SEIFilmGrainApp class - delete allocated buffers - destroy internal class - returns the number of mismatching pictures */ Void read2(InputNALUnit& nalu) { TComInputBitstream& bs = nalu.getBitstream(); Bool forbidden_zero_bit = bs.read(1); // forbidden_zero_bit if (forbidden_zero_bit != 0) { std::cerr << "Forbidden zero-bit not '0'" << std::endl; exit(1); } nalu.m_nalUnitType = (NalUnitType) bs.read(6); // nal_unit_type nalu.m_nuhLayerId = bs.read(6); // nuh_layer_id nalu.m_temporalId = bs.read(3) - 1; // nuh_temporal_id_plus1 } Void SEIFilmGrainApp::setSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics *pFgcParameters) { // Set SEI message parameters read from command line options pFgcParameters->m_filmGrainCharacteristicsCancelFlag = m_fgcSEICancelFlag; pFgcParameters->m_filmGrainCharacteristicsPersistenceFlag = m_fgcSEIPersistenceFlag; pFgcParameters->m_separateColourDescriptionPresentFlag = m_fgcSEISepColourDescPresentFlag; pFgcParameters->m_filmGrainModelId = m_fgcSEIModelID; pFgcParameters->m_blendingModeId = m_fgcSEIBlendingModeID; pFgcParameters->m_log2ScaleFactor = m_fgcSEILog2ScaleFactor; for (UInt c = 0; c < MAX_NUM_COMPONENT; c++) { pFgcParameters->m_compModel[c].bPresentFlag = m_fgcSEICompModelPresent[c]; if (pFgcParameters->m_compModel[c].bPresentFlag) { pFgcParameters->m_compModel[c].numModelValues = 1 + m_fgcSEINumModelValuesMinus1[c]; pFgcParameters->m_compModel[c].numIntensityIntervals = 1 + m_fgcSEINumIntensityIntervalMinus1[c]; pFgcParameters->m_compModel[c].intensityValues.resize(pFgcParameters->m_compModel[c].numIntensityIntervals); for (UInt i = 0; i < pFgcParameters->m_compModel[c].numIntensityIntervals; i++) { pFgcParameters->m_compModel[c].intensityValues[i].intensityIntervalLowerBound = m_fgcSEIIntensityIntervalLowerBound[c][i]; pFgcParameters->m_compModel[c].intensityValues[i].intensityIntervalUpperBound = m_fgcSEIIntensityIntervalUpperBound[c][i]; pFgcParameters->m_compModel[c].intensityValues[i].compModelValue.resize(pFgcParameters->m_compModel[c].numModelValues); for (UInt j = 0; j < pFgcParameters->m_compModel[c].numModelValues; j++) { pFgcParameters->m_compModel[c].intensityValues[i].compModelValue[j] = m_fgcSEICompModelValue[c][i][j]; } } } } } Void SEIFilmGrainApp::printSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics *pFgcParameters) { fprintf(stdout, "--------------------------------------\n"); fprintf(stdout, "fg_characteristics_cancel_flag = %d\n", pFgcParameters->m_filmGrainCharacteristicsCancelFlag); fprintf(stdout, "fg_model_id = %d\n", pFgcParameters->m_filmGrainModelId); fprintf(stdout, "fg_separate_colour_description_present_flag = %d\n", pFgcParameters->m_separateColourDescriptionPresentFlag); fprintf(stdout, "fg_blending_mode_id = %d\n", pFgcParameters->m_blendingModeId); fprintf(stdout, "fg_log2_scale_factor = %d\n", pFgcParameters->m_log2ScaleFactor); for (int c = 0; c < MAX_NUM_COMPONENT; c++) { fprintf(stdout, "fg_comp_model_present_flag[c] = %d\n", pFgcParameters->m_compModel[c].bPresentFlag); } for (int c = 0; c < MAX_NUM_COMPONENT; c++) { if (pFgcParameters->m_compModel[c].bPresentFlag) { fprintf(stdout, "num_intensity_intervals_minus1[c] = %d\n", pFgcParameters->m_compModel[c].numIntensityIntervals - 1); fprintf(stdout, "fg_num_model_values_minus1[c] = %d\n", pFgcParameters->m_compModel[c].numModelValues - 1); for (int i = 0; i < pFgcParameters->m_compModel[c].numIntensityIntervals; i++) { fprintf(stdout, "fg_intensity_interval_lower_bound[c][i] = %d\n", pFgcParameters->m_compModel[c].intensityValues[i].intensityIntervalLowerBound); fprintf(stdout, "fg_intensity_interval_upper_bound[c][i] = %d\n", pFgcParameters->m_compModel[c].intensityValues[i].intensityIntervalUpperBound); for (int j = 0; j < pFgcParameters->m_compModel[c].numModelValues; j++) { fprintf(stdout, "fg_comp_model_value[c][i][j] = %d\n", pFgcParameters->m_compModel[c].intensityValues[i].compModelValue[j]); } } } } fprintf(stdout, "fg_characteristics_persistence_flag = %d\n", pFgcParameters->m_filmGrainCharacteristicsPersistenceFlag); fprintf(stdout, "--------------------------------------\n"); } UInt SEIFilmGrainApp::process() { ifstream bitstreamFileIn(m_bitstreamFileNameIn.c_str(), ifstream::in | ifstream::binary); if (!bitstreamFileIn) { std::cerr << "failed to open bitstream file " << m_bitstreamFileNameIn.c_str() << " for reading"; exit(1); } ofstream bitstreamFileOut(m_bitstreamFileNameOut.c_str(), ifstream::out | ifstream::binary); InputByteStream bytestream(bitstreamFileIn); bitstreamFileIn.clear(); bitstreamFileIn.seekg( 0, ios::beg ); Int NALUcount = 0; Int SEIcount = 0; while (!!bitstreamFileIn) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the SEIFilmGrainApp::process() method to be called again with the same * nal unit. */ AnnexBStats stats = AnnexBStats(); InputNALUnit nalu; byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats); Bool bWrite = true; Bool bRemoveSEI = false; Bool bInsertSEI = false; // call actual decoding function if (nalu.getBitstream().getFifo().empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ std::cerr << "Warning: Attempt to process an empty NAL unit" << std::endl; } else { read2( nalu ); NALUcount++; SEIMessages SEIs; if (nalu.m_nalUnitType == NAL_UNIT_PPS && m_seiFilmGrainOption == 2) { bInsertSEI = true; SEIFilmGrainCharacteristics *sei = new SEIFilmGrainCharacteristics; setSEIFilmGrainCharacteristics(sei); if (m_seiFilmGrainPrint) { printSEIFilmGrainCharacteristics(sei); } SEIs.push_back(sei); } // end Coded Slice UnitType if (nalu.m_nalUnitType == NAL_UNIT_PREFIX_SEI && m_seiFilmGrainOption) { // parse FGC SEI m_seiReader.parseSEImessage(&(nalu.getBitstream()), SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), &std::cout); int payloadType = 0; std::list::iterator message; for (message = SEIs.begin(); message != SEIs.end(); ++message) { SEIcount++; payloadType = (*message)->payloadType(); if (payloadType == SEI::FILM_GRAIN_CHARACTERISTICS) { bRemoveSEI = true; if (m_seiFilmGrainOption == 3) // rewrite FGC SEI { SEIFilmGrainCharacteristics *fgcParameters = static_cast(*message); setSEIFilmGrainCharacteristics(fgcParameters); if (m_seiFilmGrainPrint) { printSEIFilmGrainCharacteristics(fgcParameters); } bInsertSEI = true; } } // end FGC SEI } } // end SEI UnitType // write regular NalUnit if (bWrite && !bRemoveSEI && bitstreamFileOut) { if (nalu.m_nalUnitType < 16 && m_seiFilmGrainOption == 1) { stats.m_numZeroByteBytes++; } if (nalu.m_nalUnitType < 16 && m_seiFilmGrainOption == 2) { stats.m_numZeroByteBytes--; } int iNumZeros = stats.m_numLeadingZero8BitsBytes + stats.m_numZeroByteBytes + stats.m_numStartCodePrefixBytes - 1; char ch = 0; for (int i = 0; i < iNumZeros; i++) { bitstreamFileOut.write(&ch, 1); } ch = 1; bitstreamFileOut.write(&ch, 1); bitstreamFileOut.write((const char*)nalu.getBitstream().getFifo().data(), nalu.getBitstream().getFifo().size()); } // write FGC SEI NalUnit if (bWrite && bInsertSEI && bitstreamFileOut) { Bool useLongStartCode = (nalu.m_nalUnitType == NAL_UNIT_VPS || nalu.m_nalUnitType == NAL_UNIT_SPS || nalu.m_nalUnitType == NAL_UNIT_PPS); SEIMessages currentMessages = extractSeisByType(SEIs, SEI::FILM_GRAIN_CHARACTERISTICS); OutputNALUnit outNalu(NAL_UNIT_PREFIX_SEI, nalu.m_temporalId); m_seiWriter.writeSEImessages(outNalu.m_Bitstream, currentMessages, m_parameterSetManager.getActiveSPS(), false); NALUnitEBSP naluWithHeader(outNalu); static const UChar startCodePrefix[] = { 0,0,0,1 }; if (useLongStartCode) { bitstreamFileOut.write(reinterpret_cast(startCodePrefix), 4); } else { bitstreamFileOut.write(reinterpret_cast(startCodePrefix + 1), 3); } bitstreamFileOut << naluWithHeader.m_nalUnitData.str(); } } } // end bitstreamFileIn if (m_seiFilmGrainOption) { fprintf(stdout, "\n\n========================= SUMMARY =============================== \n"); fprintf(stdout, " Total NALU count: %d \n", NALUcount); fprintf(stdout, " Total SEI count : %d \n", SEIcount); fprintf(stdout, " FGC SEI process : %d \n", m_seiFilmGrainOption); fprintf(stdout, "================================================================= \n"); } return 0; } //! \} #endif HM-HM-18.0/source/App/SEIFilmGrainApp/SEIFilmGrainApp.h000066400000000000000000000062131442026013100221600ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainApp.h \brief Decoder application class (header) */ #ifndef __SEIFILMGRAINAPP__ #define __SEIFILMGRAINAPP__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include #include "SEIFilmGrainAppCfg.h" #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComSlice.h" #include "TLibDecoder/NALread.h" #include "TLibEncoder/NALwrite.h" #include "TLibDecoder/SEIread.h" #include "TLibEncoder/SEIwrite.h" using namespace std; #if JVET_X0048_X0103_FILM_GRAIN // ==================================================================================================================== // Class definition // ==================================================================================================================== /// decoder application class class SEIFilmGrainApp : public SEIFilmGrainAppCfg { public: SEIFilmGrainApp(); virtual ~SEIFilmGrainApp() {} UInt process (); ///< main decoding function protected: ParameterSetManager m_parameterSetManager; SEIReader m_seiReader; SEIWriter m_seiWriter; Void setSEIFilmGrainCharacteristics ( SEIFilmGrainCharacteristics *pFgcParameters ); Void printSEIFilmGrainCharacteristics( SEIFilmGrainCharacteristics *pFgcParameters ); }; #endif #endif // __SEIFILMGRAINAPP__ HM-HM-18.0/source/App/SEIFilmGrainApp/SEIFilmGrainAppCfg.cpp000066400000000000000000000351111442026013100231320ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainAppCfg.cpp \brief Decoder configuration class */ #include #include #include #include "SEIFilmGrainAppCfg.h" #include "Utilities/program_options_lite.h" using namespace std; namespace po = df::program_options_lite; #if JVET_X0048_X0103_FILM_GRAIN //! \ingroup SEIFilmGrainApp //! \{ template static inline istream& operator >> (std::istream &in, SMultiValueInput &values) { return values.readValues(in); } template T SMultiValueInput::readValue(const char *&pStr, bool &bSuccess) { T val = T(); std::string s(pStr); std::replace(s.begin(), s.end(), ',', ' '); // make comma separated into space separated std::istringstream iss(s); iss >> val; bSuccess = !iss.fail() // check nothing has gone wrong && !(valmaxValIncl) // check value is within range && (int)iss.tellg() != 0 // check we've actually read something && (iss.eof() || iss.peek() == ' '); // check next character is a space, or eof pStr += (iss.eof() ? s.size() : (std::size_t)iss.tellg()); return val; } template istream& SMultiValueInput::readValues(std::istream &in) { values.clear(); string str; while (!in.eof()) { string tmp; in >> tmp; str += " " + tmp; } if (!str.empty()) { const TChar *pStr=str.c_str(); // soak up any whitespace for (; isspace(*pStr); pStr++); while (*pStr != 0) { Bool bSuccess=true; T val = readValue(pStr, bSuccess); if (!bSuccess) { in.setstate(ios::failbit); break; } if (maxNumValuesIncl != 0 && values.size() >= maxNumValuesIncl) { in.setstate(ios::failbit); break; } values.push_back(val); // soak up any whitespace and up to 1 comma. for (; isspace(*pStr); pStr++); if (*pStr == ',') { pStr++; } for (; isspace(*pStr); pStr++); } } if (values.size() < minNumValuesIncl) { in.setstate(ios::failbit); } return in; } template static inline istream& operator >> (std::istream &in, std::map &map) { T1 key; T2 value; try { in >> key; in >> value; } catch (...) { in.setstate(ios::failbit); } map[key] = value; return in; } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param argc number of arguments \param argv array of arguments */ Bool SEIFilmGrainAppCfg::parseCfg( Int argc, TChar* argv[] ) { Bool do_help = false; Int warnUnknowParameter = 0; // default values used for FGC SEI parameter parsing SMultiValueInput cfg_FgcSEIIntensityIntervalLowerBoundComp[MAX_NUM_COMPONENT]={SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256)}; SMultiValueInput cfg_FgcSEIIntensityIntervalUpperBoundComp[MAX_NUM_COMPONENT]={SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256)}; SMultiValueInput cfg_FgcSEICompModelValueComp[MAX_NUM_COMPONENT]={SMultiValueInput (0, 65535, 0, 256 * 6), SMultiValueInput (0, 65535, 0, 256 * 6), SMultiValueInput (0, 65535, 0, 256 * 6)}; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("c", po::parseConfigFile, "film grain configuration file name") ("BitstreamFileIn,b", m_bitstreamFileNameIn, string(""), "bitstream input file name") ("BitstreamFileOut,o", m_bitstreamFileNameOut, string(""), "bitstream output file name") ("SEIFilmGrainOption", m_seiFilmGrainOption, 0, "process FGC SEI option (0:disable, 1:remove, 2:insert, 3:change)" ) ("SEIFilmGrainPrint", m_seiFilmGrainPrint, false, "print output film grain characteristics SEI message (1:enable)") // film grain characteristics SEI ("SEIFGCEnabled", m_fgcSEIEnabled, false, "Control generation of the film grain characteristics SEI message") ("SEIFGCAnalysisEnabled", m_fgcSEIAnalysisEnabled, false, "Control adaptive film grain parameter estimation - film grain analysis") ("SEIFGCCancelFlag", m_fgcSEICancelFlag, false, "Specifies the persistence of any previous film grain characteristics SEI message in output order.") ("SEIFGCPersistenceFlag", m_fgcSEIPersistenceFlag, false, "Specifies the persistence of the film grain characteristics SEI message for the current layer.") ("SEIFGCPerPictureSEI", m_fgcSEIPerPictureSEI, false, "Film Grain SEI is added for each picture as speciffied in RDD5 to ensure bit accurate synthesis in tricky mode") ("SEIFGCModelID", m_fgcSEIModelID, 0u, "Specifies the film grain simulation model. 0: frequency filtering; 1: auto-regression.") ("SEIFGCSepColourDescPresentFlag", m_fgcSEISepColourDescPresentFlag, false, "Specifies the presence of a distinct colour space description for the film grain characteristics specified in the SEI message.") ("SEIFGCBlendingModeID", m_fgcSEIBlendingModeID, 0u, "Specifies the blending mode used to blend the simulated film grain with the decoded images. 0: additive; 1: multiplicative.") ("SEIFGCLog2ScaleFactor", m_fgcSEILog2ScaleFactor, 2u, "Specifies a scale factor used in the film grain characterization equations.") ("SEIFGCCompModelPresentComp0", m_fgcSEICompModelPresent[0], false, "Specifies the presence of film grain modelling on colour component 0.") ("SEIFGCCompModelPresentComp1", m_fgcSEICompModelPresent[1], false, "Specifies the presence of film grain modelling on colour component 1.") ("SEIFGCCompModelPresentComp2", m_fgcSEICompModelPresent[2], false, "Specifies the presence of film grain modelling on colour component 2.") ("SEIFGCNumIntensityIntervalMinus1Comp0", m_fgcSEINumIntensityIntervalMinus1[0], 0u, "Specifies the number of intensity intervals minus1 on colour component 0.") ("SEIFGCNumIntensityIntervalMinus1Comp1", m_fgcSEINumIntensityIntervalMinus1[1], 0u, "Specifies the number of intensity intervals minus1 on colour component 1.") ("SEIFGCNumIntensityIntervalMinus1Comp2", m_fgcSEINumIntensityIntervalMinus1[2], 0u, "Specifies the number of intensity intervals minus1 on colour component 2.") ("SEIFGCNumModelValuesMinus1Comp0", m_fgcSEINumModelValuesMinus1[0], 0u, "Specifies the number of component model values minus1 on colour component 0.") ("SEIFGCNumModelValuesMinus1Comp1", m_fgcSEINumModelValuesMinus1[1], 0u, "Specifies the number of component model values minus1 on colour component 1.") ("SEIFGCNumModelValuesMinus1Comp2", m_fgcSEINumModelValuesMinus1[2], 0u, "Specifies the number of component model values minus1 on colour component 2.") ("SEIFGCIntensityIntervalLowerBoundComp0", cfg_FgcSEIIntensityIntervalLowerBoundComp[0], cfg_FgcSEIIntensityIntervalLowerBoundComp[0], "Specifies the lower bound for the intensity intervals on colour component 0.") ("SEIFGCIntensityIntervalLowerBoundComp1", cfg_FgcSEIIntensityIntervalLowerBoundComp[1], cfg_FgcSEIIntensityIntervalLowerBoundComp[1], "Specifies the lower bound for the intensity intervals on colour component 1.") ("SEIFGCIntensityIntervalLowerBoundComp2", cfg_FgcSEIIntensityIntervalLowerBoundComp[2], cfg_FgcSEIIntensityIntervalLowerBoundComp[2], "Specifies the lower bound for the intensity intervals on colour component 2.") ("SEIFGCIntensityIntervalUpperBoundComp0", cfg_FgcSEIIntensityIntervalUpperBoundComp[0], cfg_FgcSEIIntensityIntervalUpperBoundComp[0], "Specifies the upper bound for the intensity intervals on colour component 0.") ("SEIFGCIntensityIntervalUpperBoundComp1", cfg_FgcSEIIntensityIntervalUpperBoundComp[1], cfg_FgcSEIIntensityIntervalUpperBoundComp[1], "Specifies the upper bound for the intensity intervals on colour component 1.") ("SEIFGCIntensityIntervalUpperBoundComp2", cfg_FgcSEIIntensityIntervalUpperBoundComp[2], cfg_FgcSEIIntensityIntervalUpperBoundComp[2], "Specifies the upper bound for the intensity intervals on colour component 2.") ("SEIFGCCompModelValuesComp0", cfg_FgcSEICompModelValueComp[0], cfg_FgcSEICompModelValueComp[0], "Specifies the component model values on colour component 0.") ("SEIFGCCompModelValuesComp1", cfg_FgcSEICompModelValueComp[1], cfg_FgcSEICompModelValueComp[1], "Specifies the component model values on colour component 1.") ("SEIFGCCompModelValuesComp2", cfg_FgcSEICompModelValueComp[2], cfg_FgcSEICompModelValueComp[2], "Specifies the component model values on colour component 2.") ("WarnUnknowParameter,w", warnUnknowParameter, 0, "warn for unknown configuration parameters instead of failing") ; po::setDefaults(opts); po::ErrorReporter err; const list& argv_unhandled = po::scanArgv(opts, argc, (const TChar**)argv, err); for (list::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { std::cerr << "Unhandled argument ignored: "<< *it << std::endl; } if (argc == 1 || do_help) { po::doHelp(cout, opts); return false; } if (err.is_errored) { if (!warnUnknowParameter) { /* errors have already been reported to stderr */ return false; } } if (m_bitstreamFileNameIn.empty()) { std::cerr << "No input file specified, aborting" << std::endl; return false; } if (m_bitstreamFileNameOut.empty()) { std::cerr << "No output file specified, aborting" << std::endl; return false; } // set sei film grain parameters. if (m_fgcSEIEnabled) { if (m_fgcSEIAnalysisEnabled) { fprintf(stderr, "*************************************************************************\n"); fprintf(stderr, "* WARNING: SEIFGCAnalysisEnabled needs to be set to 0! *\n"); fprintf(stderr, "*************************************************************************\n"); m_fgcSEIAnalysisEnabled = false; } if (!m_fgcSEIPerPictureSEI && !m_fgcSEIPersistenceFlag) { fprintf(stderr, "*************************************************************************\n"); fprintf(stderr, "* WARNING: SEIPerPictureSEI is set to 0, SEIPersistenceFlag needs to be set to 1! *\n"); fprintf(stderr, "*************************************************************************\n"); m_fgcSEIPersistenceFlag = true; } else if (m_fgcSEIPerPictureSEI && m_fgcSEIPersistenceFlag) { fprintf(stderr, "*************************************************************************\n"); fprintf(stderr, "* WARNING: SEIPerPictureSEI is set to 1, SEIPersistenceFlag needs to be set to 0! *\n"); fprintf(stderr, "*************************************************************************\n"); m_fgcSEIPersistenceFlag = false; } UInt numModelCtr; for (UInt c = 0; c <= 2; c++) { if (m_fgcSEICompModelPresent[c]) { numModelCtr = 0; for (UInt i = 0; i <= m_fgcSEINumIntensityIntervalMinus1[c]; i++) { m_fgcSEIIntensityIntervalLowerBound[c][i] = UChar((cfg_FgcSEIIntensityIntervalLowerBoundComp[c].values.size() > i) ? cfg_FgcSEIIntensityIntervalLowerBoundComp[c].values[i] : 0); m_fgcSEIIntensityIntervalUpperBound[c][i] = UChar((cfg_FgcSEIIntensityIntervalUpperBoundComp[c].values.size() > i) ? cfg_FgcSEIIntensityIntervalUpperBoundComp[c].values[i] : 0); for (UInt j = 0; j <= m_fgcSEINumModelValuesMinus1[c]; j++) { m_fgcSEICompModelValue[c][i][j] = UInt((cfg_FgcSEICompModelValueComp[c].values.size() > numModelCtr) ? cfg_FgcSEICompModelValueComp[c].values[numModelCtr] : 0); numModelCtr++; } } } } } return true; } SEIFilmGrainAppCfg::SEIFilmGrainAppCfg() : m_bitstreamFileNameIn() , m_bitstreamFileNameOut() , m_seiFilmGrainOption() , m_seiFilmGrainPrint(false) { } SEIFilmGrainAppCfg::~SEIFilmGrainAppCfg() { } //! \} #endifHM-HM-18.0/source/App/SEIFilmGrainApp/SEIFilmGrainAppCfg.h000066400000000000000000000076431442026013100226100ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainAppCfg.h \brief Decoder configuration class (header) */ #ifndef __SEIFILMGRAINAPPCFG__ #define __SEIFILMGRAINAPPCFG__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include #if JVET_X0048_X0103_FILM_GRAIN //! \ingroup SEIFilmGrainApp //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Decoder configuration class class SEIFilmGrainAppCfg { protected: std::string m_bitstreamFileNameIn; ///< output bitstream file name std::string m_bitstreamFileNameOut; ///< input bitstream file name Int m_seiFilmGrainOption; ///< process FGC SEI option: 0:disable, 1:remove, 2:insert, 3:change Bool m_seiFilmGrainPrint; ///< print output FGC SEI message. 1:enable // film grain characterstics sei Bool m_fgcSEIEnabled; Bool m_fgcSEIAnalysisEnabled; Bool m_fgcSEICancelFlag; Bool m_fgcSEIPersistenceFlag; Bool m_fgcSEIPerPictureSEI; UInt m_fgcSEIModelID; Bool m_fgcSEISepColourDescPresentFlag; UInt m_fgcSEIBlendingModeID; UInt m_fgcSEILog2ScaleFactor; Bool m_fgcSEICompModelPresent[MAX_NUM_COMPONENT]; UInt m_fgcSEINumModelValuesMinus1[MAX_NUM_COMPONENT]; UInt m_fgcSEINumIntensityIntervalMinus1[MAX_NUM_COMPONENT]; UInt m_fgcSEIIntensityIntervalLowerBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UInt m_fgcSEIIntensityIntervalUpperBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UInt m_fgcSEICompModelValue[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES][FG_MAX_NUM_MODEL_VALUES]; public: SEIFilmGrainAppCfg(); virtual ~SEIFilmGrainAppCfg(); Bool parseCfg ( Int argc, TChar* argv[] ); ///< initialize option class from configuration }; //! \} #endif #endif // __SEIFILMGRAINAPPCFG__ HM-HM-18.0/source/App/SEIFilmGrainApp/SEIFilmGrainMain.cpp000066400000000000000000000071771442026013100226710ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainMain.cpp \brief Decoder application main */ #include #include #include #include "SEIFilmGrainApp.h" #include "program_options_lite.h" //! \ingroup SEIFilmGrainApp //! \{ // ==================================================================================================================== // Main function // ==================================================================================================================== int main(int argc, char* argv[]) { Int returnCode = EXIT_SUCCESS; #if JVET_X0048_X0103_FILM_GRAIN // print information fprintf( stdout, "\n" ); fprintf( stdout, "HM: SEIFilmGrainApp Version %s ", NV_VERSION ); fprintf( stdout, NVM_ONOS ); fprintf( stdout, NVM_COMPILEDBY ); fprintf( stdout, NVM_BITS ); #if HHI_SIMD_OPT std::string SIMD; df::program_options_lite::Options optsSimd; optsSimd.addOptions()( "SIMD", SIMD, string( "" ), "" ); df::program_options_lite::SilentReporter err; df::program_options_lite::scanArgv( optsSimd, argc, ( const TChar** ) argv, err ); fprintf( stdout, "[SIMD=%s] ", read_x86_extension( SIMD ) ); #endif #if ENABLE_TRACING fprintf( stdout, "[ENABLE_TRACING] " ); #endif fprintf( stdout, "\n" ); SEIFilmGrainApp *pcSEIApp = new SEIFilmGrainApp; // parse configuration if(!pcSEIApp->parseCfg( argc, argv )) { returnCode = EXIT_FAILURE; return returnCode; } // starting time Double dResult; clock_t lBefore = clock(); // call decoding function if( 0 != pcSEIApp->process() ) { printf( "\n\n***ERROR*** A decoding mismatch occured: signalled md5sum does not match\n" ); returnCode = EXIT_FAILURE; } // ending time dResult = (Double)(clock()-lBefore) / CLOCKS_PER_SEC; printf("\n Total Time: %12.3f sec.\n", dResult); delete pcSEIApp; #endif return returnCode; } //! \} HM-HM-18.0/source/App/SEIRemovalApp/000077500000000000000000000000001442026013100166705ustar00rootroot00000000000000HM-HM-18.0/source/App/SEIRemovalApp/CMakeLists.txt000066400000000000000000000041011442026013100214240ustar00rootroot00000000000000# executable set( EXE_NAME SEIRemovalApp ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ) # include the output directory, where the svnrevision.h file is generated include_directories(${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries( ${EXE_NAME} TLibCommon TLibDecoder Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/SEIRemovalApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/SEIRemovalApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/SEIRemovalApp> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/SEIRemovalApp> $<$:${CMAKE_SOURCE_DIR}/bin/SEIRemovalAppStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/SEIRemovalAppStatic> $<$:${CMAKE_SOURCE_DIR}/bin/SEIRemovalAppStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/SEIRemovalAppStaticm> ) endif() # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/SEIRemovalApp/SEIRemovalApp.cpp000066400000000000000000000130531442026013100220050ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIRemovalApp.cpp \brief Decoder application class */ #include #include #include #include #include "SEIRemovalApp.h" #include "TLibDecoder/AnnexBread.h" #include "TLibDecoder/NALread.h" //! \ingroup DecoderApp //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== SEIRemovalApp::SEIRemovalApp() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in SEIRemovalApp class - delete allocated buffers - destroy internal class - returns the number of mismatching pictures */ Void read2(InputNALUnit& nalu) { TComInputBitstream& bs = nalu.getBitstream(); Bool forbidden_zero_bit = bs.read(1); // forbidden_zero_bit if (forbidden_zero_bit != 0) { std::cerr << "Forbidden zero-bit not '0'" << std::endl; exit(1); } nalu.m_nalUnitType = (NalUnitType) bs.read(6); // nal_unit_type nalu.m_nuhLayerId = bs.read(6); // nuh_layer_id nalu.m_temporalId = bs.read(3) - 1; // nuh_temporal_id_plus1 } UInt SEIRemovalApp::decode() { // Int poc; // PicList* pcListPic = NULL; ifstream bitstreamFileIn(m_bitstreamFileNameIn.c_str(), ifstream::in | ifstream::binary); if (!bitstreamFileIn) { std::cerr << "failed to open bitstream file " << m_bitstreamFileNameIn.c_str() << " for reading"; exit(1); } ofstream bitstreamFileOut(m_bitstreamFileNameOut.c_str(), ifstream::out | ifstream::binary); InputByteStream bytestream(bitstreamFileIn); bitstreamFileIn.clear(); bitstreamFileIn.seekg( 0, ios::beg ); int unitCnt = 0; while (!!bitstreamFileIn) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the SEIRemovalApp::decode() method to be called again with the same * nal unit. */ AnnexBStats stats = AnnexBStats(); InputNALUnit nalu; byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats); // call actual decoding function if (nalu.getBitstream().getFifo().empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ std::cerr << "Warning: Attempt to decode an empty NAL unit" << std::endl; } else { read2( nalu ); unitCnt++; bool bWrite = true; // just kick out all suffix SEIS bWrite &= (( !m_discardSuffixSEIs || nalu.m_nalUnitType != NAL_UNIT_SUFFIX_SEI ) && ( !m_discardPrefixSEIs || nalu.m_nalUnitType != NAL_UNIT_PREFIX_SEI )); bWrite &= unitCnt >= m_numNALUnitsToSkip; bWrite &= m_numNALUnitsToWrite < 0 || unitCnt <= m_numNALUnitsToWrite; if( bWrite ) { int iNumZeros = stats.m_numLeadingZero8BitsBytes + stats.m_numZeroByteBytes + stats.m_numStartCodePrefixBytes -1; char ch = 0; for( int i = 0 ; i < iNumZeros; i++ ) { bitstreamFileOut.write( &ch, 1 ); } ch = 1; bitstreamFileOut.write( &ch, 1 ); bitstreamFileOut.write( (const char*)nalu.getBitstream().getFifo().data(), nalu.getBitstream().getFifo().size() ); } } } return 0; } //! \} HM-HM-18.0/source/App/SEIRemovalApp/SEIRemovalApp.h000066400000000000000000000051631442026013100214550ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIRemovalApp.h \brief Decoder application class (header) */ #ifndef __SEIREMOVALAPP__ #define __SEIREMOVALAPP__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include #include "TLibCommon/CommonDef.h" #include "SEIRemovalAppCfg.h" using namespace std; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// decoder application class class SEIRemovalApp : public SEIRemovalAppCfg { public: SEIRemovalApp(); virtual ~SEIRemovalApp () {} UInt decode (); ///< main decoding function }; #endif // __SEIREMOVALAPP__ HM-HM-18.0/source/App/SEIRemovalApp/SEIRemovalAppCfg.cpp000066400000000000000000000112621442026013100224250ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIRemovalAppCfg.cpp \brief Decoder configuration class */ #include #include #include #include "SEIRemovalAppCfg.h" #include "Utilities/program_options_lite.h" using namespace std; namespace po = df::program_options_lite; //! \ingroup DecoderApp //! \{ // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param argc number of arguments \param argv array of arguments */ Bool SEIRemovalAppCfg::parseCfg( Int argc, TChar* argv[] ) { Bool do_help = false; Int warnUnknowParameter = 0; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("BitstreamFileIn,b", m_bitstreamFileNameIn, string(""), "bitstream input file name") ("BitstreamFileOut,o", m_bitstreamFileNameOut, string(""), "bitstream output file name") ("DiscardPrefixSEI,p", m_discardPrefixSEIs, false, "remove all prefix SEIs (default: 0)") ("DiscardSuffixSEI,s", m_discardSuffixSEIs, true, "remove all suffix SEIs (default: 1)") ("NumSkip", m_numNALUnitsToSkip, 0, "number of NAL units to skip (counted inclusive the units skipped with -p/-s options)" ) ("NumWrite", m_numNALUnitsToWrite, -1, "number of NAL units to write (counted inclusive the units skipped with -p/-s/--NumSkip options), -1 to disable" ) ("WarnUnknowParameter,w", warnUnknowParameter, 0, "warn for unknown configuration parameters instead of failing") ; po::setDefaults(opts); po::ErrorReporter err; const list& argv_unhandled = po::scanArgv(opts, argc, (const TChar**) argv, err); for (list::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { std::cerr << "Unhandled argument ignored: "<< *it << std::endl; } if (argc == 1 || do_help) { po::doHelp(cout, opts); return false; } if (err.is_errored) { if (!warnUnknowParameter) { /* errors have already been reported to stderr */ return false; } } if (m_bitstreamFileNameIn.empty()) { std::cerr << "No input file specified, aborting" << std::endl; return false; } if (m_bitstreamFileNameOut.empty()) { std::cerr << "No output file specified, aborting" << std::endl; return false; } return true; } SEIRemovalAppCfg::SEIRemovalAppCfg() : m_bitstreamFileNameIn() , m_bitstreamFileNameOut() , m_discardPrefixSEIs( false ) , m_discardSuffixSEIs( false ) { } SEIRemovalAppCfg::~SEIRemovalAppCfg() { } //! \} HM-HM-18.0/source/App/SEIRemovalApp/SEIRemovalAppCfg.h000066400000000000000000000056531442026013100221010ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIRemovalAppCfg.h \brief Decoder configuration class (header) */ #ifndef __SEIREMOVALAPPCFG__ #define __SEIREMOVALAPPCFG__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include //! \ingroup DecoderApp //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Decoder configuration class class SEIRemovalAppCfg { protected: std::string m_bitstreamFileNameIn; ///< output bitstream file name std::string m_bitstreamFileNameOut; ///< input bitstream file name bool m_discardPrefixSEIs; bool m_discardSuffixSEIs; int m_numNALUnitsToSkip; int m_numNALUnitsToWrite; public: SEIRemovalAppCfg(); virtual ~SEIRemovalAppCfg(); Bool parseCfg ( Int argc, TChar* argv[] ); ///< initialize option class from configuration }; //! \} #endif // __SEIREMOVALAPPCFG__ HM-HM-18.0/source/App/SEIRemovalApp/seiremovalmain.cpp000066400000000000000000000071031442026013100224100ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file decmain.cpp \brief Decoder application main */ #include #include #include #include "SEIRemovalApp.h" #include "program_options_lite.h" //! \ingroup DecoderApp //! \{ // ==================================================================================================================== // Main function // ==================================================================================================================== int main(int argc, char* argv[]) { Int returnCode = EXIT_SUCCESS; // print information fprintf( stdout, "\n" ); fprintf( stdout, "HM: SEIRemovalApp Version %s ", NV_VERSION ); fprintf( stdout, NVM_ONOS ); fprintf( stdout, NVM_COMPILEDBY ); fprintf( stdout, NVM_BITS ); #if HHI_SIMD_OPT std::string SIMD; df::program_options_lite::Options optsSimd; optsSimd.addOptions()( "SIMD", SIMD, string( "" ), "" ); df::program_options_lite::SilentReporter err; df::program_options_lite::scanArgv( optsSimd, argc, ( const TChar** ) argv, err ); fprintf( stdout, "[SIMD=%s] ", read_x86_extension( SIMD ) ); #endif #if ENABLE_TRACING fprintf( stdout, "[ENABLE_TRACING] " ); #endif fprintf( stdout, "\n" ); SEIRemovalApp *pcDecApp = new SEIRemovalApp; // parse configuration if(!pcDecApp->parseCfg( argc, argv )) { returnCode = EXIT_FAILURE; return returnCode; } // starting time Double dResult; clock_t lBefore = clock(); // call decoding function if( 0 != pcDecApp->decode() ) { printf( "\n\n***ERROR*** A decoding mismatch occured: signalled md5sum does not match\n" ); returnCode = EXIT_FAILURE; } // ending time dResult = (Double)(clock()-lBefore) / CLOCKS_PER_SEC; printf("\n Total Time: %12.3f sec.\n", dResult); delete pcDecApp; return returnCode; } //! \} HM-HM-18.0/source/App/TAppDecoder/000077500000000000000000000000001442026013100164135ustar00rootroot00000000000000HM-HM-18.0/source/App/TAppDecoder/CMakeLists.txt000066400000000000000000000051751442026013100211630ustar00rootroot00000000000000# executable set( EXE_NAME TAppDecoder ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if( HIGH_BITDEPTH ) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() if( CMAKE_COMPILER_IS_GNUCC AND BUILD_STATIC ) set( ADDITIONAL_LIBS ${ADDITIONAL_LIBS} -static -static-libgcc -static-libstdc++ ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_STATIC_LINK=1 ) endif() target_link_libraries( ${EXE_NAME} TLibCommon TLibDecoder Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/TAppDecoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/TAppDecoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/TAppDecoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/TAppDecoder> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderStatic> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderStaticm> ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/TAppDecoder/TAppDecCfg.cpp000066400000000000000000000222631442026013100210240ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppDecCfg.cpp \brief Decoder configuration class */ #include #include #include #include "TAppDecCfg.h" #include "Utilities/program_options_lite.h" #include "TLibCommon/TComChromaFormat.h" #ifdef WIN32 #define strdup _strdup #endif using namespace std; namespace po = df::program_options_lite; //! \ingroup TAppDecoder //! \{ // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param argc number of arguments \param argv array of arguments */ Bool TAppDecCfg::parseCfg( Int argc, TChar* argv[] ) { Bool do_help = false; string cfg_TargetDecLayerIdSetFile; string outputColourSpaceConvert; Int warnUnknowParameter = 0; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("BitstreamFile,b", m_bitstreamFileName, string(""), "bitstream input file name") ("ReconFile,o", m_reconFileName, string(""), "reconstructed YUV output file name\n" "YUV writing is skipped if omitted") ("WarnUnknowParameter,w", warnUnknowParameter, 0, "warn for unknown configuration parameters instead of failing") ("SkipFrames,s", m_iSkipFrame, 0, "number of frames to skip before random access") ("OutputBitDepth,d", m_outputBitDepth[CHANNEL_TYPE_LUMA], 0, "bit depth of YUV output luma component (default: use 0 for native depth)") ("OutputBitDepthC,d", m_outputBitDepth[CHANNEL_TYPE_CHROMA], 0, "bit depth of YUV output chroma component (default: use 0 for native depth)") ("OutputColourSpaceConvert", outputColourSpaceConvert, string(""), "Colour space conversion to apply to input 444 video. Permitted values are (empty string=UNCHANGED) " + getListOfColourSpaceConverts(false)) ("MaxTemporalLayer,t", m_iMaxTemporalLayer, -1, "Maximum Temporal Layer to be decoded. -1 to decode all layers") ("SEIDecodedPictureHash", m_decodedPictureHashSEIEnabled, 1, "Control handling of decoded picture hash SEI messages\n" "\t1: check hash in SEI messages if available in the bitstream\n" "\t0: ignore SEI message") ("SEINoDisplay", m_decodedNoDisplaySEIEnabled, true, "Control handling of decoded no display SEI messages") ("TarDecLayerIdSetFile,l", cfg_TargetDecLayerIdSetFile, string(""), "targetDecLayerIdSet file name. The file should include white space separated LayerId values to be decoded. Omitting the option or a value of -1 in the file decodes all layers.") ("RespectDefDispWindow,w", m_respectDefDispWindow, 0, "Only output content inside the default display window\n") ("SEIColourRemappingInfoFilename", m_colourRemapSEIFileName, string(""), "Colour Remapping YUV output file name. If empty, no remapping is applied (ignore SEI message)\n") #if JVET_X0048_X0103_FILM_GRAIN ("SEIFGSFilename", m_SEIFGSFileName, string(""), "FGS YUV output file name. If empty, no film grain is applied (ignore SEI message)\n") #endif #if SHUTTER_INTERVAL_SEI_PROCESSING ("SEIShutterIntervalPostFilename,-sii", m_shutterIntervalPostFileName, string(""), "Post Filtering with Shutter Interval SEI. If empty, no filtering is applied (ignore SEI message)\n") #endif ("SEIAnnotatedRegionsInfoFilename", m_annotatedRegionsSEIFileName, string(""), "Annotated regions output file name. If empty, no object information will be saved (ignore SEI message)\n") #if O0043_BEST_EFFORT_DECODING ("ForceDecodeBitDepth", m_forceDecodeBitDepth, 0U, "Force the decoder to operate at a particular bit-depth (best effort decoding)") #endif ("OutputDecodedSEIMessagesFilename", m_outputDecodedSEIMessagesFilename, string(""), "When non empty, output decoded SEI messages to the indicated file. If file is '-', then output to stdout\n") ("ClipOutputVideoToRec709Range", m_bClipOutputVideoToRec709Range, false, "If true then clip output video to the Rec. 709 Range on saving") #if MCTS_ENC_CHECK ("TMCTSCheck", m_tmctsCheck, false, "If enabled, the decoder checks for violations of mc_exact_sample_value_match_flag in Temporal MCTS ") #endif ; po::setDefaults(opts); po::ErrorReporter err; const list& argv_unhandled = po::scanArgv(opts, argc, (const TChar**) argv, err); for (list::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { fprintf(stderr, "Unhandled argument ignored: `%s'\n", *it); } if (argc == 1 || do_help) { po::doHelp(cout, opts); return false; } if (err.is_errored) { if (!warnUnknowParameter) { /* errors have already been reported to stderr */ return false; } } m_outputColourSpaceConvert = stringToInputColourSpaceConvert(outputColourSpaceConvert, false); if (m_outputColourSpaceConvert>=NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS) { fprintf(stderr, "Bad output colour space conversion string\n"); return false; } if (m_bitstreamFileName.empty()) { fprintf(stderr, "No input file specified, aborting\n"); return false; } if ( !cfg_TargetDecLayerIdSetFile.empty() ) { FILE* targetDecLayerIdSetFile = fopen ( cfg_TargetDecLayerIdSetFile.c_str(), "r" ); if ( targetDecLayerIdSetFile ) { Bool isLayerIdZeroIncluded = false; while ( !feof(targetDecLayerIdSetFile) ) { Int layerIdParsed = 0; if ( fscanf( targetDecLayerIdSetFile, "%d ", &layerIdParsed ) != 1 ) { if ( m_targetDecLayerIdSet.size() == 0 ) { fprintf(stderr, "No LayerId could be parsed in file %s. Decoding all LayerIds as default.\n", cfg_TargetDecLayerIdSetFile.c_str() ); } break; } if ( layerIdParsed == -1 ) // The file includes a -1, which means all LayerIds are to be decoded. { m_targetDecLayerIdSet.clear(); // Empty set means decoding all layers. break; } if ( layerIdParsed < 0 || layerIdParsed >= MAX_NUM_LAYER_IDS ) { fprintf(stderr, "Warning! Parsed LayerId %d is not within allowed range [0,%d]. Ignoring this value.\n", layerIdParsed, MAX_NUM_LAYER_IDS-1 ); } else { isLayerIdZeroIncluded = layerIdParsed == 0 ? true : isLayerIdZeroIncluded; m_targetDecLayerIdSet.push_back ( layerIdParsed ); } } fclose (targetDecLayerIdSetFile); if ( m_targetDecLayerIdSet.size() > 0 && !isLayerIdZeroIncluded ) { fprintf(stderr, "TargetDecLayerIdSet must contain LayerId=0, aborting" ); return false; } } else { fprintf(stderr, "File %s could not be opened. Using all LayerIds as default.\n", cfg_TargetDecLayerIdSetFile.c_str() ); } } return true; } //! \} HM-HM-18.0/source/App/TAppDecoder/TAppDecCfg.h000066400000000000000000000126731442026013100204750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppDecCfg.h \brief Decoder configuration class (header) */ #ifndef __TAPPDECCFG__ #define __TAPPDECCFG__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include //! \ingroup TAppDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Decoder configuration class class TAppDecCfg { protected: std::string m_bitstreamFileName; ///< input bitstream file name std::string m_reconFileName; ///< output reconstruction file name Int m_iSkipFrame; ///< counter for frames prior to the random access point to skip Int m_outputBitDepth[MAX_NUM_CHANNEL_TYPE]; ///< bit depth used for writing output InputColourSpaceConversion m_outputColourSpaceConvert; Int m_iMaxTemporalLayer; ///< maximum temporal layer to be decoded Int m_decodedPictureHashSEIEnabled; ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message Bool m_decodedNoDisplaySEIEnabled; ///< Enable(true)/disable(false) writing only pictures that get displayed based on the no display SEI message std::string m_colourRemapSEIFileName; ///< output Colour Remapping file name #if JVET_X0048_X0103_FILM_GRAIN std::string m_SEIFGSFileName; ///< output reconstruction file name #endif #if SHUTTER_INTERVAL_SEI_PROCESSING std::string m_shutterIntervalPostFileName; ///< output Post Filtering file name #endif std::string m_annotatedRegionsSEIFileName; ///< annotated regions file name std::vector m_targetDecLayerIdSet; ///< set of LayerIds to be included in the sub-bitstream extraction process. Int m_respectDefDispWindow; ///< Only output content inside the default display window #if O0043_BEST_EFFORT_DECODING UInt m_forceDecodeBitDepth; ///< if non-zero, force the bit depth at the decoder (best effort decoding) #endif std::string m_outputDecodedSEIMessagesFilename; ///< filename to output decoded SEI messages to. If '-', then use stdout. If empty, do not output details. Bool m_bClipOutputVideoToRec709Range; ///< If true, clip the output video to the Rec 709 range on saving. #if MCTS_ENC_CHECK Bool m_tmctsCheck; #endif public: TAppDecCfg() : m_bitstreamFileName() , m_reconFileName() , m_iSkipFrame(0) // m_outputBitDepth array initialised below , m_outputColourSpaceConvert(IPCOLOURSPACE_UNCHANGED) , m_iMaxTemporalLayer(-1) , m_decodedPictureHashSEIEnabled(0) , m_decodedNoDisplaySEIEnabled(false) , m_colourRemapSEIFileName() #if JVET_X0048_X0103_FILM_GRAIN , m_SEIFGSFileName() #endif #if SHUTTER_INTERVAL_SEI_PROCESSING , m_shutterIntervalPostFileName() #endif , m_annotatedRegionsSEIFileName() , m_targetDecLayerIdSet() , m_respectDefDispWindow(0) #if O0043_BEST_EFFORT_DECODING , m_forceDecodeBitDepth(0) #endif , m_outputDecodedSEIMessagesFilename() , m_bClipOutputVideoToRec709Range(false) #if MCTS_ENC_CHECK , m_tmctsCheck(false) #endif { for (UInt channelTypeIndex = 0; channelTypeIndex < MAX_NUM_CHANNEL_TYPE; channelTypeIndex++) { m_outputBitDepth[channelTypeIndex] = 0; } } virtual ~TAppDecCfg() {} Bool parseCfg ( Int argc, TChar* argv[] ); ///< initialize option class from configuration }; //! \} #endif HM-HM-18.0/source/App/TAppDecoder/TAppDecTop.cpp000066400000000000000000001445121442026013100210710ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppDecTop.cpp \brief Decoder application class */ #include #include #include #include #include #include "TAppDecTop.h" #include "TLibDecoder/AnnexBread.h" #include "TLibDecoder/NALread.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif //! \ingroup TAppDecoder //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== TAppDecTop::TAppDecTop() : m_iPOCLastDisplay(-MAX_INT) ,m_pcSeiColourRemappingInfoPrevious(NULL) { } Void TAppDecTop::create() { } Void TAppDecTop::destroy() { m_bitstreamFileName.clear(); m_reconFileName.clear(); #if JVET_X0048_X0103_FILM_GRAIN m_SEIFGSFileName.clear(); #endif #if SHUTTER_INTERVAL_SEI_PROCESSING m_shutterIntervalPostFileName.clear(); #endif } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in TDecTop class - delete allocated buffers - destroy internal class . */ Void TAppDecTop::decode() { Int poc; TComList* pcListPic = NULL; ifstream bitstreamFile(m_bitstreamFileName.c_str(), ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_bitstreamFileName.c_str()); exit(EXIT_FAILURE); } InputByteStream bytestream(bitstreamFile); if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-") { m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out); if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good()) { fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str()); exit(EXIT_FAILURE); } } // create & initialize internal classes xCreateDecLib(); xInitDecLib (); m_iPOCLastDisplay += m_iSkipFrame; // set the last displayed POC correctly for skip forward. // clear contents of colour-remap-information-SEI output file if (!m_colourRemapSEIFileName.empty()) { std::ofstream ofile(m_colourRemapSEIFileName.c_str()); if (!ofile.good() || !ofile.is_open()) { fprintf(stderr, "\nUnable to open file '%s' for writing colour-remap-information-SEI video\n", m_colourRemapSEIFileName.c_str()); exit(EXIT_FAILURE); } } // clear contents of annotated-Regions-SEI output file if (!m_annotatedRegionsSEIFileName.empty()) { std::ofstream ofile(m_annotatedRegionsSEIFileName.c_str()); if (!ofile.good() || !ofile.is_open()) { fprintf(stderr, "\nUnable to open file '%s' for writing annotated-Regions-SEI\n", m_annotatedRegionsSEIFileName.c_str()); exit(EXIT_FAILURE); } } // main decoder loop Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen) #if JVET_X0048_X0103_FILM_GRAIN Bool openedSEIFGSFile = false; // reconstruction file (with FGS) not yet opened. (must be performed after SPS is seen) #endif Bool loopFiltered = false; #if SHUTTER_INTERVAL_SEI_PROCESSING Bool openedPostFile = false; setShutterFilterFlag(!m_shutterIntervalPostFileName.empty()); // not apply shutter interval SEI processing if filename is not specified. m_cTDecTop.setShutterFilterFlag(getShutterFilterFlag()); #endif while (!!bitstreamFile) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics()); streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes()); #else streampos location = bitstreamFile.tellg(); #endif AnnexBStats stats = AnnexBStats(); InputNALUnit nalu; byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats); // call actual decoding function Bool bNewPicture = false; if (nalu.getBitstream().getFifo().empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n"); } else { read(nalu); if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu) ) { bNewPicture = false; } else { bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); if (bNewPicture) { bitstreamFile.clear(); /* location points to the current nalunit payload[1] due to the * need for the annexB parser to read three extra bytes. * [1] except for the first NAL unit in the file * (but bNewPicture doesn't happen then) */ #if RExt__DECODER_DEBUG_BIT_STATISTICS bitstreamFile.seekg(location); bytestream.reset(); TComCodingStatistics::SetStatistics(backupStats); #else bitstreamFile.seekg(location-streamoff(3)); bytestream.reset(); #endif } } } if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cTDecTop.getFirstSliceInSequence () ) { if (!loopFiltered || bitstreamFile) { m_cTDecTop.executeLoopFilters(poc, pcListPic); } loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS); if (nalu.m_nalUnitType == NAL_UNIT_EOS) { m_cTDecTop.setFirstSliceInSequence(true); } } else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && m_cTDecTop.getFirstSliceInSequence () ) { m_cTDecTop.setFirstSliceInPicture (true); } if( pcListPic ) { if ( (!m_reconFileName.empty()) && (!openedReconFile) ) { const BitDepths &bitDepths=pcListPic->front()->getPicSym()->getSPS().getBitDepths(); // use bit depths of first reconstructed picture. for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { if (m_outputBitDepth[channelType] == 0) { m_outputBitDepth[channelType] = bitDepths.recon[channelType]; } } m_cTVideoIOYuvReconFile.open( m_reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode openedReconFile = true; } #if JVET_X0048_X0103_FILM_GRAIN // Initialize file handle to write output with film grain if ((!m_SEIFGSFileName.empty()) && (!openedSEIFGSFile)) { const BitDepths &bitDepths = pcListPic->front()->getPicSym()->getSPS().getBitDepths(); // use bit depths of first reconstructed picture. for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { if (m_outputBitDepth[channelType] == 0) { m_outputBitDepth[channelType] = bitDepths.recon[channelType]; } } m_cTVideoIOYuvSEIFGSFile.open(m_SEIFGSFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon); // write mode openedSEIFGSFile = true; } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING TComList::iterator iterPic = pcListPic->begin(); TComPic* pcPic = *(iterPic); SEIMessages shutterIntervalInfo = getSeisByType(pcPic->getSEIs(), SEI::SHUTTER_INTERVAL_INFO); if (!m_shutterIntervalPostFileName.empty()) { if (shutterIntervalInfo.size() > 0) { SEIShutterIntervalInfo *seiShutterIntervalInfo = (SEIShutterIntervalInfo*) *(shutterIntervalInfo.begin()); if (!seiShutterIntervalInfo->m_siiFixedSIwithinCLVS) { UInt arraySize = seiShutterIntervalInfo->m_siiMaxSubLayersMinus1 + 1; UInt numUnitsLFR = seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI[0]; UInt numUnitsHFR = seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI[arraySize - 1]; setShutterFilterFlag(numUnitsLFR == 2 * numUnitsHFR); const TComSPS* activeSPS = &(pcListPic->front()->getPicSym()->getSPS()); if (numUnitsLFR == 2 * numUnitsHFR && activeSPS->getMaxTLayers() == 1 && activeSPS->getMaxDecPicBuffering(0) == 1) { fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled for single TempLayer and single frame in DPB\n"); setShutterFilterFlag(false); } } else { fprintf(stderr, "Warning: Shutter Interval SEI message processing is disabled for fixed shutter interval case\n"); setShutterFilterFlag(false); } } else { fprintf(stderr, "Warning: Shutter Interval information should be specified in SII-SEI message\n"); setShutterFilterFlag(false); } } if ((!m_shutterIntervalPostFileName.empty()) && (!openedPostFile) && getShutterFilterFlag()) { const BitDepths &bitDepths = pcListPic->front()->getPicSym()->getSPS().getBitDepths(); for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { if (m_outputBitDepth[channelType] == 0) { m_outputBitDepth[channelType] = bitDepths.recon[channelType]; } } std::ofstream ofile(m_shutterIntervalPostFileName.c_str()); if (!ofile.good() || !ofile.is_open()) { fprintf(stderr, "\nUnable to open file '%s' for writing shutter-interval-SEI video\n", m_shutterIntervalPostFileName.c_str()); exit(EXIT_FAILURE); } m_cTVideoIOYuvSIIPostFile.open(m_shutterIntervalPostFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon); // write mode openedPostFile = true; } #endif // write reconstruction to file if( bNewPicture ) { xWriteOutput( pcListPic, nalu.m_temporalId ); } if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() ) { m_cTDecTop.checkNoOutputPriorPics( pcListPic ); m_cTDecTop.setNoOutputPriorPicsFlag (false); } if ( bNewPicture && ( nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) ) { xFlushOutput( pcListPic ); } if (nalu.m_nalUnitType == NAL_UNIT_EOS) { xWriteOutput( pcListPic, nalu.m_temporalId ); m_cTDecTop.setFirstSliceInPicture (false); } // write reconstruction to file -- for additional bumping as defined in C.5.2.3 if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31) { xWriteOutput( pcListPic, nalu.m_temporalId ); } } } xFlushOutput( pcListPic ); // delete buffers m_cTDecTop.deletePicBuffer(); // destroy internal classes xDestroyDecLib(); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Void TAppDecTop::xCreateDecLib() { // create decoder class m_cTDecTop.create(); } Void TAppDecTop::xDestroyDecLib() { if ( !m_reconFileName.empty() ) { m_cTVideoIOYuvReconFile.close(); } #if JVET_X0048_X0103_FILM_GRAIN if (!m_SEIFGSFileName.empty()) { m_cTVideoIOYuvSEIFGSFile.close(); } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { m_cTVideoIOYuvSIIPostFile.close(); } #endif // destroy decoder class m_cTDecTop.destroy(); if (m_pcSeiColourRemappingInfoPrevious != NULL) { delete m_pcSeiColourRemappingInfoPrevious; m_pcSeiColourRemappingInfoPrevious = NULL; } m_arObjects.clear(); m_arLabels.clear(); } Void TAppDecTop::xInitDecLib() { // initialize decoder class m_cTDecTop.init(); m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled); #if MCTS_ENC_CHECK m_cTDecTop.setTMctsCheckEnabled(m_tmctsCheck); #endif #if O0043_BEST_EFFORT_DECODING m_cTDecTop.setForceDecodeBitDepth(m_forceDecodeBitDepth); #endif if (!m_outputDecodedSEIMessagesFilename.empty()) { std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout; m_cTDecTop.setDecodedSEIMessageOutputStream(&os); } if (m_pcSeiColourRemappingInfoPrevious != NULL) { delete m_pcSeiColourRemappingInfoPrevious; m_pcSeiColourRemappingInfoPrevious = NULL; } m_arObjects.clear(); m_arLabels.clear(); } /** \param pcListPic list of pictures to be written to file \param tId temporal sub-layer ID */ Void TAppDecTop::xWriteOutput( TComList* pcListPic, UInt tId ) { if (pcListPic->empty()) { return; } TComList::iterator iterPic = pcListPic->begin(); Int numPicsNotYetDisplayed = 0; Int dpbFullness = 0; const TComSPS* activeSPS = &(pcListPic->front()->getPicSym()->getSPS()); UInt numReorderPicsHighestTid; UInt maxDecPicBufferingHighestTid; UInt maxNrSublayers = activeSPS->getMaxTLayers(); if(m_iMaxTemporalLayer == -1 || m_iMaxTemporalLayer >= maxNrSublayers) { numReorderPicsHighestTid = activeSPS->getNumReorderPics(maxNrSublayers-1); maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(maxNrSublayers-1); } else { numReorderPicsHighestTid = activeSPS->getNumReorderPics(m_iMaxTemporalLayer); maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(m_iMaxTemporalLayer); } while (iterPic != pcListPic->end()) { TComPic* pcPic = *(iterPic); if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay) { numPicsNotYetDisplayed++; dpbFullness++; } else if(pcPic->getSlice( 0 )->isReferenced()) { dpbFullness++; } iterPic++; } iterPic = pcListPic->begin(); if (numPicsNotYetDisplayed>2) { iterPic++; } TComPic* pcPic = *(iterPic); if (numPicsNotYetDisplayed>2 && pcPic->isField()) //Field Decoding { TComList::iterator endPic = pcListPic->end(); endPic--; iterPic = pcListPic->begin(); while (iterPic != endPic) { TComPic* pcPicTop = *(iterPic); iterPic++; TComPic* pcPicBottom = *(iterPic); if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && (numPicsNotYetDisplayed > numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) && (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) && (pcPicTop->getPOC() == m_iPOCLastDisplay+1 || m_iPOCLastDisplay < 0)) { // write to file numPicsNotYetDisplayed = numPicsNotYetDisplayed-2; if ( !m_reconFileName.empty() ) { const Window &conf = pcPicTop->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window(); const Bool isTff = pcPicTop->isTopField(); Bool display = true; if( m_decodedNoDisplaySEIEnabled ) { SEIMessages noDisplay = getSeisByType(pcPic->getSEIs(), SEI::NO_DISPLAY ); const SEINoDisplay *nd = ( noDisplay.size() > 0 ) ? (SEINoDisplay*) *(noDisplay.begin()) : NULL; if( (nd != NULL) && nd->m_noDisplay ) { display = false; } } if (display) { m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff ); } } // update POC of display order m_iPOCLastDisplay = pcPicBottom->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true ) { pcPicTop->setReconMark(false); // mark it should be extended later pcPicTop->getPicYuvRec()->setBorderExtension( false ); } if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true ) { pcPicBottom->setReconMark(false); // mark it should be extended later pcPicBottom->getPicYuvRec()->setBorderExtension( false ); } pcPicTop->setOutputMark(false); pcPicBottom->setOutputMark(false); } } } else if (!pcPic->isField()) //Frame Decoding { iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { pcPic = *(iterPic); if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay && (numPicsNotYetDisplayed > numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid)) { // write to file numPicsNotYetDisplayed--; if(pcPic->getSlice(0)->isReferenced() == false) { dpbFullness--; } if ( !m_reconFileName.empty() ) { const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); } #if JVET_X0048_X0103_FILM_GRAIN // Perform FGS on decoded frame and write to output FGS file if (!m_SEIFGSFileName.empty()) { const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvSEIFGSFile.write(pcPic->getPicYuvDisp(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range); } #endif if (!m_annotatedRegionsSEIFileName.empty()) { xOutputAnnotatedRegions(pcPic); } if (!m_colourRemapSEIFileName.empty()) { xOutputColourRemapPic(pcPic); } #if SHUTTER_INTERVAL_SEI_PROCESSING if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { pcPic->xOutputPostFilteredPic(pcPic, pcListPic); const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvSIIPostFile.write( pcPic->getPicYuvPostRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); } #endif // update POC of display order m_iPOCLastDisplay = pcPic->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true ) { pcPic->setReconMark(false); // mark it should be extended later pcPic->getPicYuvRec()->setBorderExtension( false ); } pcPic->setOutputMark(false); } iterPic++; } } } /** \param pcListPic list of pictures to be written to file */ Void TAppDecTop::xFlushOutput( TComList* pcListPic ) { if(!pcListPic || pcListPic->empty()) { return; } TComList::iterator iterPic = pcListPic->begin(); iterPic = pcListPic->begin(); TComPic* pcPic = *(iterPic); if (pcPic->isField()) //Field Decoding { TComList::iterator endPic = pcListPic->end(); endPic--; TComPic *pcPicTop, *pcPicBottom = NULL; while (iterPic != endPic) { pcPicTop = *(iterPic); iterPic++; pcPicBottom = *(iterPic); if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) ) { // write to file if ( !m_reconFileName.empty() ) { const Window &conf = pcPicTop->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window(); const Bool isTff = pcPicTop->isTopField(); m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff ); } // update POC of display order m_iPOCLastDisplay = pcPicBottom->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true ) { pcPicTop->setReconMark(false); // mark it should be extended later pcPicTop->getPicYuvRec()->setBorderExtension( false ); } if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true ) { pcPicBottom->setReconMark(false); // mark it should be extended later pcPicBottom->getPicYuvRec()->setBorderExtension( false ); } pcPicTop->setOutputMark(false); pcPicBottom->setOutputMark(false); if(pcPicTop) { pcPicTop->destroy(); delete pcPicTop; pcPicTop = NULL; } } } if(pcPicBottom) { pcPicBottom->destroy(); delete pcPicBottom; pcPicBottom = NULL; } } else //Frame decoding { while (iterPic != pcListPic->end()) { pcPic = *(iterPic); if ( pcPic->getOutputMark() ) { // write to file if ( !m_reconFileName.empty() ) { const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); } #if JVET_X0048_X0103_FILM_GRAIN // Perform FGS on decoded frame and write to output FGS file if (!m_SEIFGSFileName.empty()) { const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvSEIFGSFile.write(pcPic->getPicYuvDisp(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range); } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { pcPic->xOutputPostFilteredPic(pcPic, pcListPic); const Window &conf = pcPic->getConformanceWindow(); const Window defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvSIIPostFile.write( pcPic->getPicYuvPostRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); } #endif if (!m_colourRemapSEIFileName.empty()) { xOutputColourRemapPic(pcPic); } if (!m_annotatedRegionsSEIFileName.empty()) { xOutputAnnotatedRegions(pcPic); } // update POC of display order m_iPOCLastDisplay = pcPic->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true ) { pcPic->setReconMark(false); // mark it should be extended later pcPic->getPicYuvRec()->setBorderExtension( false ); } pcPic->setOutputMark(false); } #if SHUTTER_INTERVAL_SEI_PROCESSING if (pcPic != NULL && (m_shutterIntervalPostFileName.empty() || !getShutterFilterFlag())) #else if(pcPic != NULL) #endif { pcPic->destroy(); delete pcPic; pcPic = NULL; } iterPic++; } #if SHUTTER_INTERVAL_SEI_PROCESSING if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { pcPic = *(iterPic); if (pcPic != NULL) { pcPic->destroy(); delete pcPic; pcPic = NULL; } iterPic++; } } #endif } pcListPic->clear(); m_iPOCLastDisplay = -MAX_INT; } /** \param nalu Input nalu to check whether its LayerId is within targetDecLayerIdSet */ Bool TAppDecTop::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu ) { if ( m_targetDecLayerIdSet.size() == 0 ) // By default, the set is empty, meaning all LayerIds are allowed { return true; } for (std::vector::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++) { if ( nalu->m_nuhLayerId == (*it) ) { return true; } } return false; } Void TAppDecTop::xOutputColourRemapPic(TComPic* pcPic) { const TComSPS &sps=pcPic->getPicSym()->getSPS(); SEIMessages colourRemappingInfo = getSeisByType(pcPic->getSEIs(), SEI::COLOUR_REMAPPING_INFO ); SEIColourRemappingInfo *seiColourRemappingInfo = ( colourRemappingInfo.size() > 0 ) ? (SEIColourRemappingInfo*) *(colourRemappingInfo.begin()) : NULL; if (colourRemappingInfo.size() > 1) { printf ("Warning: Got multiple Colour Remapping Information SEI messages. Using first."); } if (seiColourRemappingInfo) { applyColourRemapping(*pcPic->getPicYuvRec(), *seiColourRemappingInfo, sps); // save the last CRI SEI received if (m_pcSeiColourRemappingInfoPrevious == NULL) { m_pcSeiColourRemappingInfoPrevious = new SEIColourRemappingInfo(); } m_pcSeiColourRemappingInfoPrevious->copyFrom(*seiColourRemappingInfo); } else // using the last CRI SEI received { // TODO: prevent persistence of CRI SEI across C(L)VS. if (m_pcSeiColourRemappingInfoPrevious != NULL) { if (m_pcSeiColourRemappingInfoPrevious->m_colourRemapPersistenceFlag == false) { printf("Warning No SEI-CRI message is present for the current picture, persistence of the CRI is not managed\n"); } applyColourRemapping(*pcPic->getPicYuvRec(), *m_pcSeiColourRemappingInfoPrevious, sps); } } } Void TAppDecTop::xOutputAnnotatedRegions(TComPic* pcPic) { // Check if any annotated region SEI has arrived SEIMessages annotatedRegionSEIs = getSeisByType(pcPic->getSEIs(), SEI::ANNOTATED_REGIONS); for(auto it=annotatedRegionSEIs.begin(); it!=annotatedRegionSEIs.end(); it++) { const SEIAnnotatedRegions &seiAnnotatedRegions = *(SEIAnnotatedRegions*)(*it); if (seiAnnotatedRegions.m_hdr.m_cancelFlag) { m_arObjects.clear(); m_arLabels.clear(); } else { if (m_arHeader.m_receivedSettingsOnce) { // validate those settings that must stay constant are constant. assert(m_arHeader.m_occludedObjectFlag == seiAnnotatedRegions.m_hdr.m_occludedObjectFlag); assert(m_arHeader.m_partialObjectFlagPresentFlag == seiAnnotatedRegions.m_hdr.m_partialObjectFlagPresentFlag); assert(m_arHeader.m_objectConfidenceInfoPresentFlag == seiAnnotatedRegions.m_hdr.m_objectConfidenceInfoPresentFlag); assert((!m_arHeader.m_objectConfidenceInfoPresentFlag) || m_arHeader.m_objectConfidenceLength == seiAnnotatedRegions.m_hdr.m_objectConfidenceLength); } else { m_arHeader.m_receivedSettingsOnce=true; m_arHeader=seiAnnotatedRegions.m_hdr; // copy the settings. } // Process label updates if (seiAnnotatedRegions.m_hdr.m_objectLabelPresentFlag) { for(auto srcIt=seiAnnotatedRegions.m_annotatedLabels.begin(); srcIt!=seiAnnotatedRegions.m_annotatedLabels.end(); srcIt++) { const UInt labIdx = srcIt->first; if (srcIt->second.labelValid) { m_arLabels[labIdx] = srcIt->second.label; } else { m_arLabels.erase(labIdx); } } } // Process object updates for(auto srcIt=seiAnnotatedRegions.m_annotatedRegions.begin(); srcIt!=seiAnnotatedRegions.m_annotatedRegions.end(); srcIt++) { UInt objIdx = srcIt->first; const SEIAnnotatedRegions::AnnotatedRegionObject &src =srcIt->second; if (src.objectCancelFlag) { m_arObjects.erase(objIdx); } else { auto destIt = m_arObjects.find(objIdx); if (destIt == m_arObjects.end()) { //New object arrived, needs to be appended to the map of tracked objects m_arObjects[objIdx] = src; } else //Existing object, modifications to be done { SEIAnnotatedRegions::AnnotatedRegionObject &dst=destIt->second; if (seiAnnotatedRegions.m_hdr.m_objectLabelPresentFlag && src.objectLabelValid) { dst.objectLabelValid=true; dst.objLabelIdx = src.objLabelIdx; } if (src.boundingBoxValid) { dst.boundingBoxTop = src.boundingBoxTop ; dst.boundingBoxLeft = src.boundingBoxLeft ; dst.boundingBoxWidth = src.boundingBoxWidth ; dst.boundingBoxHeight = src.boundingBoxHeight; if (seiAnnotatedRegions.m_hdr.m_partialObjectFlagPresentFlag) { dst.partialObjectFlag = src.partialObjectFlag; } if (seiAnnotatedRegions.m_hdr.m_objectConfidenceInfoPresentFlag) { dst.objectConfidence = src.objectConfidence; } } } } } } } if (!m_arObjects.empty()) { FILE *fp_persist = fopen(m_annotatedRegionsSEIFileName.c_str(), "ab"); if (fp_persist == NULL) { std::cout << "Not able to open file for writing persist SEI messages" << std::endl; } else { fprintf(fp_persist, "\n"); fprintf(fp_persist, "Number of objects = %d\n", (Int)m_arObjects.size()); for (auto it = m_arObjects.begin(); it != m_arObjects.end(); ++it) { fprintf(fp_persist, "Object Idx = %d\n", it->first); fprintf(fp_persist, "Object Top = %d\n", it->second.boundingBoxTop); fprintf(fp_persist, "Object Left = %d\n", it->second.boundingBoxLeft); fprintf(fp_persist, "Object Width = %d\n", it->second.boundingBoxWidth); fprintf(fp_persist, "Object Height = %d\n", it->second.boundingBoxHeight); if (it->second.objectLabelValid) { auto labelIt=m_arLabels.find(it->second.objLabelIdx); fprintf(fp_persist, "Object Label = %s\n", labelIt!=m_arLabels.end() ? (labelIt->second.c_str()) : ""); } if (m_arHeader.m_partialObjectFlagPresentFlag) { fprintf(fp_persist, "Object Partial = %d\n", it->second.partialObjectFlag?1:0); } if (m_arHeader.m_objectConfidenceInfoPresentFlag) { fprintf(fp_persist, "Object Conf = %d\n", it->second.objectConfidence); } } fclose(fp_persist); } } } // compute lut from SEI // use at lutPoints points aligned on a power of 2 value // SEI Lut must be in ascending values of coded Values static std::vector initColourRemappingInfoLut(const Int bitDepth_in, // bit-depth of the input values of the LUT const Int nbDecimalValues, // Position of the fixed point const std::vector &lut, const Int maxValue, // maximum output value const Int lutOffset) { const Int lutPoints = (1 << bitDepth_in) + 1 ; std::vector retLut(lutPoints); // missing values: need to define default values before first definition (check codedValue[0] == 0) Int iTargetPrev = (lut.size() && lut[0].codedValue == 0) ? lut[0].targetValue: 0; Int startPivot = (lut.size())? ((lut[0].codedValue == 0)? 1: 0): 1; Int iCodedPrev = 0; // set max value with the coded bit-depth // + ((1 << nbDecimalValues) - 1) is for the added bits const Int maxValueFixedPoint = (maxValue << nbDecimalValues) + ((1 << nbDecimalValues) - 1); Int iValue = 0; for ( Int iPivot=startPivot ; iPivot < (Int)lut.size(); iPivot++ ) { Int iCodedNext = lut[iPivot].codedValue; Int iTargetNext = lut[iPivot].targetValue; // ensure correct bit depth and avoid overflow in lut address Int iCodedNext_bitDepth = std::min(iCodedNext, (1 << bitDepth_in)); const Int divValue = (iCodedNext - iCodedPrev > 0)? (iCodedNext - iCodedPrev): 1; const Int lutValInit = (lutOffset + iTargetPrev) << nbDecimalValues; const Int roundValue = divValue / 2; for ( ; iValue 0)? (iCodedNext - iCodedPrev): 1; const Int lutValInit = (lutOffset + iTargetPrev) << nbDecimalValues; const Int roundValue = divValue / 2; for ( ; iValue<=iCodedNext; iValue++ ) { Int value = iValue; Int interpol = ((((value-iCodedPrev) * (iTargetNext - iTargetPrev)) << nbDecimalValues) + roundValue) / divValue; retLut[iValue] = std::min(lutValInit + interpol , maxValueFixedPoint); } } return retLut; } static Void initColourRemappingInfoLuts(std::vector (&preLut)[3], std::vector (&postLut)[3], SEIColourRemappingInfo &pCriSEI, const Int maxBitDepth) { Int internalBitDepth = pCriSEI.m_colourRemapBitDepth; for ( Int c=0 ; c<3 ; c++ ) { std::sort(pCriSEI.m_preLut[c].begin(), pCriSEI.m_preLut[c].end()); // ensure preLut is ordered in ascending values of codedValues preLut[c] = initColourRemappingInfoLut(pCriSEI.m_colourRemapInputBitDepth, maxBitDepth - pCriSEI.m_colourRemapInputBitDepth, pCriSEI.m_preLut[c], ((1 << internalBitDepth) - 1), 0); //Fill preLut std::sort(pCriSEI.m_postLut[c].begin(), pCriSEI.m_postLut[c].end()); // ensure postLut is ordered in ascending values of codedValues postLut[c] = initColourRemappingInfoLut(pCriSEI.m_colourRemapBitDepth, maxBitDepth - pCriSEI.m_colourRemapBitDepth, pCriSEI.m_postLut[c], (1 << internalBitDepth) - 1, 0); //Fill postLut } } // apply lut. // Input lut values are aligned on power of 2 boundaries static Int applyColourRemappingInfoLut1D(Int inVal, const std::vector &lut, const Int inValPrecisionBits) { const Int roundValue = (inValPrecisionBits)? 1 << (inValPrecisionBits - 1): 0; inVal = std::min(std::max(0, inVal), (Int)(((lut.size()-1) << inValPrecisionBits))); Int index = (Int) std::min((inVal >> inValPrecisionBits), (Int)(lut.size()-2)); Int outVal = (( inVal - (index<> inValPrecisionBits; outVal += lut[index] ; return outVal; } static Int applyColourRemappingInfoMatrix(const Int (&colourRemapCoeffs)[3], const Int postOffsetShift, const Int p0, const Int p1, const Int p2, const Int offset) { Int YUVMat = (colourRemapCoeffs[0]* p0 + colourRemapCoeffs[1]* p1 + colourRemapCoeffs[2]* p2 + offset) >> postOffsetShift; return YUVMat; } static Void setColourRemappingInfoMatrixOffset(Int (&matrixOffset)[3], Int offset0, Int offset1, Int offset2) { matrixOffset[0] = offset0; matrixOffset[1] = offset1; matrixOffset[2] = offset2; } static Void setColourRemappingInfoMatrixOffsets( Int (&matrixInputOffset)[3], Int (&matrixOutputOffset)[3], const Int bitDepth, const Bool crInputFullRangeFlag, const Int crInputMatrixCoefficients, const Bool crFullRangeFlag, const Int crMatrixCoefficients) { // set static matrix offsets Int crInputOffsetLuma = (crInputFullRangeFlag)? 0:-(16 << (bitDepth-8)); Int crOffsetLuma = (crFullRangeFlag)? 0:(16 << (bitDepth-8)); Int crInputOffsetChroma = 0; Int crOffsetChroma = 0; switch(crInputMatrixCoefficients) { case MATRIX_COEFFICIENTS_RGB: crInputOffsetChroma = 0; if(!crInputFullRangeFlag) { fprintf(stderr, "WARNING: crInputMatrixCoefficients set to MATRIX_COEFFICIENTS_RGB and crInputFullRangeFlag not set\n"); crInputOffsetLuma = 0; } break; case MATRIX_COEFFICIENTS_UNSPECIFIED: case MATRIX_COEFFICIENTS_BT709: case MATRIX_COEFFICIENTS_BT2020_NON_CONSTANT_LUMINANCE: crInputOffsetChroma = -(1 << (bitDepth-1)); break; default: fprintf(stderr, "WARNING: crInputMatrixCoefficients set to undefined value: %d\n", crInputMatrixCoefficients); } switch(crMatrixCoefficients) { case MATRIX_COEFFICIENTS_RGB: crOffsetChroma = 0; if(!crFullRangeFlag) { fprintf(stderr, "WARNING: crMatrixCoefficients set to MATRIX_COEFFICIENTS_RGB and crInputFullRangeFlag not set\n"); crOffsetLuma = 0; } break; case MATRIX_COEFFICIENTS_UNSPECIFIED: case MATRIX_COEFFICIENTS_BT709: case MATRIX_COEFFICIENTS_BT2020_NON_CONSTANT_LUMINANCE: crOffsetChroma = (1 << (bitDepth-1)); break; default: fprintf(stderr, "WARNING: crMatrixCoefficients set to undefined value: %d\n", crMatrixCoefficients); } setColourRemappingInfoMatrixOffset(matrixInputOffset, crInputOffsetLuma, crInputOffsetChroma, crInputOffsetChroma); setColourRemappingInfoMatrixOffset(matrixOutputOffset, crOffsetLuma, crOffsetChroma, crOffsetChroma); } Void TAppDecTop::applyColourRemapping(const TComPicYuv& pic, SEIColourRemappingInfo& criSEI, const TComSPS &activeSPS) { const Int maxBitDepth = 16; // create colour remapped picture if( !criSEI.m_colourRemapCancelFlag && pic.getChromaFormat()!=CHROMA_400) // 4:0:0 not supported. { const Int iHeight = pic.getHeight(COMPONENT_Y); const Int iWidth = pic.getWidth(COMPONENT_Y); const ChromaFormat chromaFormatIDC = pic.getChromaFormat(); TComPicYuv picYuvColourRemapped; picYuvColourRemapped.createWithoutCUInfo( iWidth, iHeight, chromaFormatIDC ); const Int iStrideIn = pic.getStride(COMPONENT_Y); const Int iCStrideIn = pic.getStride(COMPONENT_Cb); const Int iStrideOut = picYuvColourRemapped.getStride(COMPONENT_Y); const Int iCStrideOut = picYuvColourRemapped.getStride(COMPONENT_Cb); const Bool b444 = ( pic.getChromaFormat() == CHROMA_444 ); const Bool b422 = ( pic.getChromaFormat() == CHROMA_422 ); const Bool b420 = ( pic.getChromaFormat() == CHROMA_420 ); std::vector preLut[3]; std::vector postLut[3]; Int matrixInputOffset[3]; Int matrixOutputOffset[3]; const Pel *YUVIn[MAX_NUM_COMPONENT]; Pel *YUVOut[MAX_NUM_COMPONENT]; YUVIn[COMPONENT_Y] = pic.getAddr(COMPONENT_Y); YUVIn[COMPONENT_Cb] = pic.getAddr(COMPONENT_Cb); YUVIn[COMPONENT_Cr] = pic.getAddr(COMPONENT_Cr); YUVOut[COMPONENT_Y] = picYuvColourRemapped.getAddr(COMPONENT_Y); YUVOut[COMPONENT_Cb] = picYuvColourRemapped.getAddr(COMPONENT_Cb); YUVOut[COMPONENT_Cr] = picYuvColourRemapped.getAddr(COMPONENT_Cr); const Int bitDepth = criSEI.m_colourRemapBitDepth; BitDepths bitDepthsCriFile; bitDepthsCriFile.recon[CHANNEL_TYPE_LUMA] = bitDepth; bitDepthsCriFile.recon[CHANNEL_TYPE_CHROMA] = bitDepth; // Different bitdepth is not implemented const Int postOffsetShift = criSEI.m_log2MatrixDenom; const Int matrixRound = 1 << (postOffsetShift - 1); const Int postLutInputPrecision = (maxBitDepth - criSEI.m_colourRemapBitDepth); if ( ! criSEI.m_colourRemapVideoSignalInfoPresentFlag ) // setting default { setColourRemappingInfoMatrixOffsets(matrixInputOffset, matrixOutputOffset, maxBitDepth, activeSPS.getVuiParameters()->getVideoFullRangeFlag(), activeSPS.getVuiParameters()->getMatrixCoefficients(), activeSPS.getVuiParameters()->getVideoFullRangeFlag(), activeSPS.getVuiParameters()->getMatrixCoefficients()); } else { setColourRemappingInfoMatrixOffsets(matrixInputOffset, matrixOutputOffset, maxBitDepth, activeSPS.getVuiParameters()->getVideoFullRangeFlag(), activeSPS.getVuiParameters()->getMatrixCoefficients(), criSEI.m_colourRemapFullRangeFlag, criSEI.m_colourRemapMatrixCoefficients); } // add matrix rounding to output matrix offsets matrixOutputOffset[0] = (matrixOutputOffset[0] << postOffsetShift) + matrixRound; matrixOutputOffset[1] = (matrixOutputOffset[1] << postOffsetShift) + matrixRound; matrixOutputOffset[2] = (matrixOutputOffset[2] << postOffsetShift) + matrixRound; // Merge matrixInputOffset and matrixOutputOffset to matrixOutputOffset matrixOutputOffset[0] += applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[0], 0, matrixInputOffset[0], matrixInputOffset[1], matrixInputOffset[2], 0); matrixOutputOffset[1] += applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[1], 0, matrixInputOffset[0], matrixInputOffset[1], matrixInputOffset[2], 0); matrixOutputOffset[2] += applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[2], 0, matrixInputOffset[0], matrixInputOffset[1], matrixInputOffset[2], 0); // rescaling output: include CRI/output frame difference const Int scaleShiftOut_neg = abs(bitDepth - maxBitDepth); const Int scaleOut_round = 1 << (scaleShiftOut_neg-1); initColourRemappingInfoLuts(preLut, postLut, criSEI, maxBitDepth); assert(pic.getChromaFormat() != CHROMA_400); const Int hs = pic.getComponentScaleX(ComponentID(COMPONENT_Cb)); const Int maxOutputValue = (1 << bitDepth) - 1; for( Int y = 0; y < iHeight; y++ ) { for( Int x = 0; x < iWidth; x++ ) { const Int xc = (x>>hs); Bool computeChroma = b444 || ((b422 || !(y&1)) && !(x&1)); Int YUVPre_0 = applyColourRemappingInfoLut1D(YUVIn[COMPONENT_Y][x], preLut[0], 0); Int YUVPre_1 = applyColourRemappingInfoLut1D(YUVIn[COMPONENT_Cb][xc], preLut[1], 0); Int YUVPre_2 = applyColourRemappingInfoLut1D(YUVIn[COMPONENT_Cr][xc], preLut[2], 0); Int YUVMat_0 = applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[0], postOffsetShift, YUVPre_0, YUVPre_1, YUVPre_2, matrixOutputOffset[0]); Int YUVLutB_0 = applyColourRemappingInfoLut1D(YUVMat_0, postLut[0], postLutInputPrecision); YUVOut[COMPONENT_Y][x] = std::min(maxOutputValue, (YUVLutB_0 + scaleOut_round) >> scaleShiftOut_neg); if( computeChroma ) { Int YUVMat_1 = applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[1], postOffsetShift, YUVPre_0, YUVPre_1, YUVPre_2, matrixOutputOffset[1]); Int YUVLutB_1 = applyColourRemappingInfoLut1D(YUVMat_1, postLut[1], postLutInputPrecision); YUVOut[COMPONENT_Cb][xc] = std::min(maxOutputValue, (YUVLutB_1 + scaleOut_round) >> scaleShiftOut_neg); Int YUVMat_2 = applyColourRemappingInfoMatrix(criSEI.m_colourRemapCoeffs[2], postOffsetShift, YUVPre_0, YUVPre_1, YUVPre_2, matrixOutputOffset[2]); Int YUVLutB_2 = applyColourRemappingInfoLut1D(YUVMat_2, postLut[2], postLutInputPrecision); YUVOut[COMPONENT_Cr][xc] = std::min(maxOutputValue, (YUVLutB_2 + scaleOut_round) >> scaleShiftOut_neg); } } YUVIn[COMPONENT_Y] += iStrideIn; YUVOut[COMPONENT_Y] += iStrideOut; if( !(b420 && !(y&1)) ) { YUVIn[COMPONENT_Cb] += iCStrideIn; YUVIn[COMPONENT_Cr] += iCStrideIn; YUVOut[COMPONENT_Cb] += iCStrideOut; YUVOut[COMPONENT_Cr] += iCStrideOut; } } //Write remapped picture in display order picYuvColourRemapped.dump( m_colourRemapSEIFileName, bitDepthsCriFile, true ); picYuvColourRemapped.destroy(); } } //! \} HM-HM-18.0/source/App/TAppDecoder/TAppDecTop.h000066400000000000000000000115431442026013100205330ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppDecTop.h \brief Decoder application class (header) */ #ifndef __TAPPDECTOP__ #define __TAPPDECTOP__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "Utilities/TVideoIOYuv.h" #include "TLibCommon/TComList.h" #include "TLibCommon/TComPicYuv.h" #include "TLibDecoder/TDecTop.h" #include "TAppDecCfg.h" //! \ingroup TAppDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// decoder application class class TAppDecTop : public TAppDecCfg { private: // class interface TDecTop m_cTDecTop; ///< decoder class TVideoIOYuv m_cTVideoIOYuvReconFile; ///< reconstruction YUV class #if JVET_X0048_X0103_FILM_GRAIN TVideoIOYuv m_cTVideoIOYuvSEIFGSFile; ///< reconstruction YUV class #endif #if SHUTTER_INTERVAL_SEI_PROCESSING Bool m_ShutterFilterEnable; ///< enable Post-processing with Shutter Interval SEI TVideoIOYuv m_cTVideoIOYuvSIIPostFile; ///< post-filtered YUV class #endif // for output control Int m_iPOCLastDisplay; ///< last POC in display order std::ofstream m_seiMessageFileStream; ///< Used for outputing SEI messages. SEIColourRemappingInfo* m_pcSeiColourRemappingInfoPrevious; SEIAnnotatedRegions::AnnotatedRegionHeader m_arHeader; std::map m_arObjects; std::map m_arLabels; public: TAppDecTop(); virtual ~TAppDecTop() {} Void create (); ///< create internal members Void destroy (); ///< destroy internal members Void decode (); ///< main decoding function UInt getNumberOfChecksumErrorsDetected() const { return m_cTDecTop.getNumberOfChecksumErrorsDetected(); } #if SHUTTER_INTERVAL_SEI_PROCESSING Bool getShutterFilterFlag() const { return m_ShutterFilterEnable; } Void setShutterFilterFlag(Bool value) { m_ShutterFilterEnable = value; } #endif protected: Void xCreateDecLib (); ///< create internal classes Void xDestroyDecLib (); ///< destroy internal classes Void xInitDecLib (); ///< initialize decoder class Void xWriteOutput ( TComList* pcListPic , UInt tId); ///< write YUV to file Void xFlushOutput ( TComList* pcListPic ); ///< flush all remaining decoded pictures to file Bool isNaluWithinTargetDecLayerIdSet ( InputNALUnit* nalu ); ///< check whether given Nalu is within targetDecLayerIdSet private: Void applyColourRemapping(const TComPicYuv& pic, SEIColourRemappingInfo& pCriSEI, const TComSPS &activeSPS); Void xOutputColourRemapPic(TComPic* pcPic); Void xOutputAnnotatedRegions(TComPic* pcPic); }; //! \} #endif HM-HM-18.0/source/App/TAppDecoder/decmain.cpp000066400000000000000000000064771442026013100205350ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file decmain.cpp \brief Decoder application main */ #include #include #include #include "TAppDecTop.h" //! \ingroup TAppDecoder //! \{ // ==================================================================================================================== // Main function // ==================================================================================================================== int main(int argc, char* argv[]) { Int returnCode = EXIT_SUCCESS; TAppDecTop cTAppDecTop; // print information fprintf( stdout, "\n" ); fprintf( stdout, "HM software: Decoder Version [%s] (including RExt)", NV_VERSION ); fprintf( stdout, NVM_ONOS ); fprintf( stdout, NVM_COMPILEDBY ); fprintf( stdout, NVM_BITS ); fprintf( stdout, "\n" ); // create application decoder class cTAppDecTop.create(); // parse configuration if(!cTAppDecTop.parseCfg( argc, argv )) { cTAppDecTop.destroy(); returnCode = EXIT_FAILURE; return returnCode; } // starting time Double dResult; clock_t lBefore = clock(); // call decoding function cTAppDecTop.decode(); if (cTAppDecTop.getNumberOfChecksumErrorsDetected() != 0) { printf("\n\n***ERROR*** A decoding mismatch occured: signalled md5sum does not match\n"); returnCode = EXIT_FAILURE; } // ending time dResult = (Double)(clock()-lBefore) / CLOCKS_PER_SEC; printf("\n Total Time: %12.3f sec.\n", dResult); // destroy application decoder class cTAppDecTop.destroy(); return returnCode; } //! \} HM-HM-18.0/source/App/TAppDecoderAnalyser/000077500000000000000000000000001442026013100201125ustar00rootroot00000000000000HM-HM-18.0/source/App/TAppDecoderAnalyser/CMakeLists.txt000066400000000000000000000056471442026013100226660ustar00rootroot00000000000000# executable set( EXE_NAME TAppDecoderAnalyser) # get source files file( GLOB SRC_FILES "../TAppDecoder/*.cpp" ) # get include files file( GLOB INC_FILES "../TAppDecoder/*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__DECODER_DEBUG_BIT_STATISTICS=1 ) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__DECODER_DEBUG_TOOL_STATISTICS=1 ) if( HIGH_BITDEPTH ) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() if( CMAKE_COMPILER_IS_GNUCC AND BUILD_STATIC ) set( ADDITIONAL_LIBS ${ADDITIONAL_LIBS} -static -static-libgcc -static-libstdc++ ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_STATIC_LINK=1 ) endif() target_link_libraries( ${EXE_NAME} TLibCommonAnalyser TLibDecoderAnalyser Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/TAppDecoderAnalyser> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/TAppDecoderAnalyser> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/TAppDecoderAnalyser> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/TAppDecoderAnalyser> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderAnalyserStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderAnalyserStatic> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderAnalyserStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/TAppDecoderAnalyserStaticm> ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/TAppEncoder/000077500000000000000000000000001442026013100164255ustar00rootroot00000000000000HM-HM-18.0/source/App/TAppEncoder/CMakeLists.txt000066400000000000000000000055441442026013100211750ustar00rootroot00000000000000# executable set( EXE_NAME TAppEncoder ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) # extend the stack size on windows to 2MB set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:0x200000" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if( HIGH_BITDEPTH ) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() if( CMAKE_COMPILER_IS_GNUCC AND BUILD_STATIC ) set( ADDITIONAL_LIBS ${ADDITIONAL_LIBS} -static -static-libgcc -static-libstdc++ ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_STATIC_LINK=1 ) endif() target_link_libraries( ${EXE_NAME} TLibCommon TLibEncoder TLibDecoder Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( EXTENSION_360_VIDEO ) target_link_libraries( ${EXE_NAME} Lib360 AppEncHelper360 ) endif() if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/TAppEncoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/TAppEncoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/TAppEncoder> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/TAppEncoder> $<$:${CMAKE_SOURCE_DIR}/bin/TAppEncoderStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/TAppEncoderStatic> $<$:${CMAKE_SOURCE_DIR}/bin/TAppEncoderStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/TAppEncoderStaticm> ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/TAppEncoder/TAppEncCfg.cpp000066400000000000000000007270301442026013100210540ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppEncCfg.cpp \brief Handle encoder configuration parameters */ #include #include #include #include #include #include #include #include "TLibCommon/TComRom.h" #if DPB_ENCODER_USAGE_CHECK #include "TLibCommon/ProfileLevelTierFeatures.h" #endif template static inline std::istream& operator >> (std::istream &in, std::map &map); #include "TAppEncCfg.h" #include "Utilities/program_options_lite.h" #include "TLibEncoder/TEncRateCtrl.h" #ifdef WIN32 #define strdup _strdup #endif #define MACRO_TO_STRING_HELPER(val) #val #define MACRO_TO_STRING(val) MACRO_TO_STRING_HELPER(val) using namespace std; enum UIProfileName // this is used for determining profile strings, where multiple profiles map to a single profile idc with various constraint flag combinations { UI_NONE = 0, UI_MAIN = 1, UI_MAIN10 = 2, UI_MAIN10_STILL_PICTURE=10002, UI_MAINSTILLPICTURE = 3, UI_MAINREXT = 4, UI_HIGHTHROUGHPUTREXT = 5, // The following are RExt profiles, which would map to the MAINREXT profile idc. // The enumeration indicates the bit-depth constraint in the bottom 2 digits // the chroma format in the next digit // the intra constraint in the next digit (1 for no intra constraint, 2 for intra constraint) // If it is a RExt still picture, there is a '1' for the top digit. UI_MONOCHROME_8 = 1008, UI_MONOCHROME_12 = 1012, UI_MONOCHROME_16 = 1016, UI_MAIN_12 = 1112, UI_MAIN_422_10 = 1210, UI_MAIN_422_12 = 1212, UI_MAIN_444 = 1308, UI_MAIN_444_10 = 1310, UI_MAIN_444_12 = 1312, UI_MAIN_444_16 = 1316, // non-standard profile definition, used for development purposes UI_MAIN_INTRA = 2108, UI_MAIN_10_INTRA = 2110, UI_MAIN_12_INTRA = 2112, UI_MAIN_422_10_INTRA = 2210, UI_MAIN_422_12_INTRA = 2212, UI_MAIN_444_INTRA = 2308, UI_MAIN_444_10_INTRA = 2310, UI_MAIN_444_12_INTRA = 2312, UI_MAIN_444_16_INTRA = 2316, UI_MAIN_444_STILL_PICTURE = 11308, UI_MAIN_444_16_STILL_PICTURE = 12316, // The following are high throughput profiles, which would map to the HIGHTHROUGHPUTREXT profile idc. // The enumeration indicates the bit-depth constraint in the bottom 2 digits // the chroma format in the next digit // the intra constraint in the next digit // There is a '2' for the top digit to indicate it is high throughput profile UI_HIGHTHROUGHPUT_444 = 21308, UI_HIGHTHROUGHPUT_444_10 = 21310, UI_HIGHTHROUGHPUT_444_14 = 21314, UI_HIGHTHROUGHPUT_444_16_INTRA = 22316 }; constexpr int TF_DEFAULT_REFS = 4; //! \ingroup TAppEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== TAppEncCfg::TAppEncCfg() : m_inputColourSpaceConvert(IPCOLOURSPACE_UNCHANGED) , m_snrInternalColourSpace(false) , m_outputInternalColourSpace(false) #if EXTENSION_360_VIDEO , m_ext360(*this) #endif { m_aidQP = NULL; m_startOfCodedInterval = NULL; m_codedPivotValue = NULL; m_targetPivotValue = NULL; } TAppEncCfg::~TAppEncCfg() { if ( m_aidQP ) { delete[] m_aidQP; } if ( m_startOfCodedInterval ) { delete[] m_startOfCodedInterval; m_startOfCodedInterval = NULL; } if ( m_codedPivotValue ) { delete[] m_codedPivotValue; m_codedPivotValue = NULL; } if ( m_targetPivotValue ) { delete[] m_targetPivotValue; m_targetPivotValue = NULL; } } Void TAppEncCfg::create() { } Void TAppEncCfg::destroy() { } std::istringstream &operator>>(std::istringstream &in, GOPEntry &entry) //input { in>>entry.m_sliceType; in>>entry.m_POC; in>>entry.m_QPOffset; in>>entry.m_QPOffsetModelOffset; in>>entry.m_QPOffsetModelScale; in>>entry.m_CbQPoffset; in>>entry.m_CrQPoffset; in>>entry.m_QPFactor; in>>entry.m_tcOffsetDiv2; in>>entry.m_betaOffsetDiv2; in>>entry.m_temporalId; in>>entry.m_numRefPicsActive; in>>entry.m_numRefPics; for ( Int i = 0; i < entry.m_numRefPics; i++ ) { in>>entry.m_referencePics[i]; } in>>entry.m_interRPSPrediction; if (entry.m_interRPSPrediction==1) { in>>entry.m_deltaRPS; in>>entry.m_numRefIdc; for ( Int i = 0; i < entry.m_numRefIdc; i++ ) { in>>entry.m_refIdc[i]; } } else if (entry.m_interRPSPrediction==2) { in>>entry.m_deltaRPS; } return in; } Bool confirmPara(Bool bflag, const TChar* message); static inline ChromaFormat numberToChromaFormat(const Int val) { switch (val) { case 400: return CHROMA_400; break; case 420: return CHROMA_420; break; case 422: return CHROMA_422; break; case 444: return CHROMA_444; break; default: return NUM_CHROMA_FORMAT; } } static const struct MapStrToProfile { const TChar* str; Profile::Name value; } strToProfile[] = { {"none", Profile::NONE }, {"main", Profile::MAIN }, {"main10", Profile::MAIN10 }, {"main-still-picture", Profile::MAINSTILLPICTURE }, {"main10-still-picture", Profile::MAIN10 }, {"main-RExt", Profile::MAINREXT }, {"high-throughput-RExt", Profile::HIGHTHROUGHPUTREXT } }; static const struct MapStrToUIProfileName { const TChar* str; UIProfileName value; } strToUIProfileName[] = { {"none", UI_NONE }, {"main", UI_MAIN }, {"main10", UI_MAIN10 }, {"main10_still_picture", UI_MAIN10_STILL_PICTURE }, {"main10-still-picture", UI_MAIN10_STILL_PICTURE }, {"main_still_picture", UI_MAINSTILLPICTURE }, {"main-still-picture", UI_MAINSTILLPICTURE }, {"main_RExt", UI_MAINREXT }, {"main-RExt", UI_MAINREXT }, {"main_rext", UI_MAINREXT }, {"main-rext", UI_MAINREXT }, {"high_throughput_RExt", UI_HIGHTHROUGHPUTREXT }, {"high-throughput-RExt", UI_HIGHTHROUGHPUTREXT }, {"high_throughput_rext", UI_HIGHTHROUGHPUTREXT }, {"high-throughput-rext", UI_HIGHTHROUGHPUTREXT }, {"monochrome", UI_MONOCHROME_8 }, {"monochrome12", UI_MONOCHROME_12 }, {"monochrome16", UI_MONOCHROME_16 }, {"main12", UI_MAIN_12 }, {"main_422_10", UI_MAIN_422_10 }, {"main_422_12", UI_MAIN_422_12 }, {"main_444", UI_MAIN_444 }, {"main_444_10", UI_MAIN_444_10 }, {"main_444_12", UI_MAIN_444_12 }, {"main_444_16", UI_MAIN_444_16 }, {"main_intra", UI_MAIN_INTRA }, {"main_10_intra", UI_MAIN_10_INTRA }, {"main_12_intra", UI_MAIN_12_INTRA }, {"main_422_10_intra", UI_MAIN_422_10_INTRA}, {"main_422_12_intra", UI_MAIN_422_12_INTRA}, {"main_444_intra", UI_MAIN_444_INTRA }, {"main_444_still_picture", UI_MAIN_444_STILL_PICTURE }, {"main_444_10_intra", UI_MAIN_444_10_INTRA}, {"main_444_12_intra", UI_MAIN_444_12_INTRA}, {"main_444_16_intra", UI_MAIN_444_16_INTRA}, {"main_444_16_still_picture", UI_MAIN_444_16_STILL_PICTURE }, {"high_throughput_444", UI_HIGHTHROUGHPUT_444 }, {"high_throughput_444_10", UI_HIGHTHROUGHPUT_444_10 }, {"high_throughput_444_14", UI_HIGHTHROUGHPUT_444_14 }, {"high_throughput_444_16_intra", UI_HIGHTHROUGHPUT_444_16_INTRA } }; static const UIProfileName validRExtHighThroughPutProfileNames[2/* intraConstraintFlag*/][4/* bit depth constraint 8=0, 10=1, 12=2, 16=3*/]= { { UI_HIGHTHROUGHPUT_444, UI_HIGHTHROUGHPUT_444_10, UI_HIGHTHROUGHPUT_444_14, UI_NONE }, // intraConstraintFlag 0 - 8-bit,10-bit,14-bit and 16-bit { UI_NONE, UI_NONE, UI_NONE, UI_HIGHTHROUGHPUT_444_16_INTRA } // intraConstraintFlag 1 - 8-bit,10-bit,14-bit and 16-bit }; static const UIProfileName validRExtProfileNames[2/* intraConstraintFlag*/][4/* bit depth constraint 8=0, 10=1, 12=2, 16=3*/][4/*chroma format*/]= { { { UI_MONOCHROME_8, UI_NONE, UI_NONE, UI_MAIN_444 }, // 8-bit inter for 400, 420, 422 and 444 { UI_NONE, UI_NONE, UI_MAIN_422_10, UI_MAIN_444_10 }, // 10-bit inter for 400, 420, 422 and 444 { UI_MONOCHROME_12, UI_MAIN_12, UI_MAIN_422_12, UI_MAIN_444_12 }, // 12-bit inter for 400, 420, 422 and 444 { UI_MONOCHROME_16, UI_NONE, UI_NONE, UI_MAIN_444_16 } // 16-bit inter for 400, 420, 422 and 444 (the latter is non standard used for development) }, { { UI_NONE, UI_MAIN_INTRA, UI_NONE, UI_MAIN_444_INTRA }, // 8-bit intra for 400, 420, 422 and 444 { UI_NONE, UI_MAIN_10_INTRA, UI_MAIN_422_10_INTRA, UI_MAIN_444_10_INTRA }, // 10-bit intra for 400, 420, 422 and 444 { UI_NONE, UI_MAIN_12_INTRA, UI_MAIN_422_12_INTRA, UI_MAIN_444_12_INTRA }, // 12-bit intra for 400, 420, 422 and 444 { UI_NONE, UI_NONE, UI_NONE, UI_MAIN_444_16_INTRA } // 16-bit intra for 400, 420, 422 and 444 } }; static const struct MapStrToTier { const TChar* str; Level::Tier value; } strToTier[] = { {"main", Level::MAIN}, {"high", Level::HIGH}, }; static const struct MapStrToLevel { const TChar* str; Level::Name value; } strToLevel[] = { {"none",Level::NONE}, {"1", Level::LEVEL1}, {"2", Level::LEVEL2}, {"2.1", Level::LEVEL2_1}, {"3", Level::LEVEL3}, {"3.1", Level::LEVEL3_1}, {"4", Level::LEVEL4}, {"4.1", Level::LEVEL4_1}, {"5", Level::LEVEL5}, {"5.1", Level::LEVEL5_1}, {"5.2", Level::LEVEL5_2}, {"6", Level::LEVEL6}, {"6.1", Level::LEVEL6_1}, {"6.2", Level::LEVEL6_2}, #if JVET_X0079_MODIFIED_BITRATES {"6.3", Level::LEVEL6_3}, #endif {"8.5", Level::LEVEL8_5}, }; #if !DPB_ENCODER_USAGE_CHECK #if JVET_X0079_MODIFIED_BITRATES UInt g_uiMaxCpbSize[2][28] = { // LEVEL1, LEVEL2, LEVEL2_1, LEVEL3, LEVEL3_1, LEVEL4, LEVEL4_1, LEVEL5, LEVEL5_1, LEVEL5_2, LEVEL6, LEVEL6_1, LEVEL6_2, LEVEL6_3 { 0, 0, 0, 0, 350000, 0, 0, 0, 1500000, 3000000, 0, 0, 6000000, 10000000, 0, 0, 12000000, 20000000, 0, 0, 25000000, 40000000, 60000000, 0, 60000000, 120000000, 240000000, 240000000 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30000000, 50000000, 0, 0, 100000000, 160000000, 240000000, 0, 240000000, 480000000, 800000000, 1600000000 } }; #else UInt g_uiMaxCpbSize[2][21] = { // LEVEL1, LEVEL2,LEVEL2_1, LEVEL3, LEVEL3_1, LEVEL4, LEVEL4_1, LEVEL5, LEVEL5_1, LEVEL5_2, LEVEL6, LEVEL6_1, LEVEL6_2 { 0, 0, 0, 350000, 0, 0, 1500000, 3000000, 0, 6000000, 10000000, 0, 12000000, 20000000, 0, 25000000, 40000000, 60000000, 60000000, 120000000, 240000000 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30000000, 50000000, 0, 100000000, 160000000, 240000000, 240000000, 480000000, 800000000 } }; #endif #endif static const struct MapStrToCostMode { const TChar* str; CostMode value; } strToCostMode[] = { {"lossy", COST_STANDARD_LOSSY}, {"sequence_level_lossless", COST_SEQUENCE_LEVEL_LOSSLESS}, {"lossless", COST_LOSSLESS_CODING}, {"mixed_lossless_lossy", COST_MIXED_LOSSLESS_LOSSY_CODING} }; static const struct MapStrToScalingListMode { const TChar* str; ScalingListMode value; } strToScalingListMode[] = { {"0", SCALING_LIST_OFF}, {"1", SCALING_LIST_DEFAULT}, {"2", SCALING_LIST_FILE_READ}, {"off", SCALING_LIST_OFF}, {"default", SCALING_LIST_DEFAULT}, {"file", SCALING_LIST_FILE_READ} }; template static std::string enumToString(P map[], UInt mapLen, const T val) { for (UInt i = 0; i < mapLen; i++) { if (val == map[i].value) { return map[i].str; } } return std::string(); } template static istream& readStrToEnum(P map[], UInt mapLen, istream &in, T &val) { string str; in >> str; UInt i=0; for (; i < mapLen && str!=map[i].str; i++); if (i < mapLen) { val = map[i].value; } else { in.setstate(ios::failbit); } return in; } //inline to prevent compiler warnings for "unused static function" static inline istream& operator >> (istream &in, UIProfileName &profile) { return readStrToEnum(strToUIProfileName, sizeof(strToUIProfileName)/sizeof(*strToUIProfileName), in, profile); } namespace Level { static inline istream& operator >> (istream &in, Tier &tier) { return readStrToEnum(strToTier, sizeof(strToTier)/sizeof(*strToTier), in, tier); } static inline istream& operator >> (istream &in, Name &level) { return readStrToEnum(strToLevel, sizeof(strToLevel)/sizeof(*strToLevel), in, level); } } static inline istream& operator >> (istream &in, CostMode &mode) { return readStrToEnum(strToCostMode, sizeof(strToCostMode)/sizeof(*strToCostMode), in, mode); } static inline istream& operator >> (istream &in, ScalingListMode &mode) { return readStrToEnum(strToScalingListMode, sizeof(strToScalingListMode)/sizeof(*strToScalingListMode), in, mode); } #if !JVET_X0048_X0103_FILM_GRAIN template struct SMultiValueInput { const T minValIncl; const T maxValIncl; const std::size_t minNumValuesIncl; const std::size_t maxNumValuesIncl; // Use 0 for unlimited std::vector values; SMultiValueInput() : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values() { } SMultiValueInput(std::vector &defaults) : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values(defaults) { } SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues=0, std::size_t maxNumberValues=0) : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values() { } SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues, std::size_t maxNumberValues, const T* defValues, const UInt numDefValues) : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values(defValues, defValues+numDefValues) { } SMultiValueInput &operator=(const std::vector &userValues) { values=userValues; return *this; } SMultiValueInput &operator=(const SMultiValueInput &userValues) { values=userValues.values; return *this; } T readValue(const TChar *&pStr, Bool &bSuccess); istream& readValues(std::istream &in); }; #endif template static inline istream& operator >> (std::istream &in, SMultiValueInput &values) { return values.readValues(in); } template T SMultiValueInput::readValue(const char *&pStr, bool &bSuccess) { T val=T(); std::string s(pStr); std::replace(s.begin(), s.end(), ',', ' '); // make comma separated into space separated std::istringstream iss(s); iss>>val; bSuccess=!iss.fail() // check nothing has gone wrong && !(valmaxValIncl) // check value is within range && (int)iss.tellg() != 0 // check we've actually read something && (iss.eof() || iss.peek()==' '); // check next character is a space, or eof pStr+= (iss.eof() ? s.size() : (std::size_t)iss.tellg()); return val; } template istream& SMultiValueInput::readValues(std::istream &in) { values.clear(); string str; while (!in.eof()) { string tmp; in >> tmp; str+=" " + tmp; } if (!str.empty()) { const TChar *pStr=str.c_str(); // soak up any whitespace for(;isspace(*pStr);pStr++); while (*pStr != 0) { Bool bSuccess=true; T val=readValue(pStr, bSuccess); if (!bSuccess) { in.setstate(ios::failbit); break; } if (maxNumValuesIncl != 0 && values.size() >= maxNumValuesIncl) { in.setstate(ios::failbit); break; } values.push_back(val); // soak up any whitespace and up to 1 comma. for(;isspace(*pStr);pStr++); if (*pStr == ',') { pStr++; } for(;isspace(*pStr);pStr++); } } if (values.size() < minNumValuesIncl) { in.setstate(ios::failbit); } return in; } template static inline istream& operator >> (std::istream &in, TAppEncCfg::OptionalValue &value) { in >> std::ws; if (in.eof()) { value.bPresent=false; } else { in >> value.value; value.bPresent=true; } return in; } template static inline istream& operator >> (std::istream &in, std::map &map) { T1 key; T2 value; try { in >> key; in >> value; } catch (...) { in.setstate(ios::failbit); } map[key] = value; return in; } static Void automaticallySelectRExtProfile(const Bool bUsingGeneralRExtTools, const Bool bUsingChromaQPAdjustment, const Bool bUsingExtendedPrecision, const Bool bIntraConstraintFlag, UInt &bitDepthConstraint, ChromaFormat &chromaFormatConstraint, const Int maxBitDepth, const ChromaFormat chromaFormat) { // Try to choose profile, according to table in Q1013. UInt trialBitDepthConstraint=maxBitDepth; if (trialBitDepthConstraint<8) { trialBitDepthConstraint=8; } else if (trialBitDepthConstraint==9 || trialBitDepthConstraint==11) { trialBitDepthConstraint++; } else if (trialBitDepthConstraint>12) { trialBitDepthConstraint=16; } // both format and bit depth constraints are unspecified if (bUsingExtendedPrecision || trialBitDepthConstraint==16) { bitDepthConstraint = 16; chromaFormatConstraint = (!bIntraConstraintFlag && chromaFormat==CHROMA_400) ? CHROMA_400 : CHROMA_444; } else if (bUsingGeneralRExtTools) { if (chromaFormat == CHROMA_400 && !bIntraConstraintFlag) { bitDepthConstraint = 16; chromaFormatConstraint = CHROMA_400; } else { bitDepthConstraint = trialBitDepthConstraint; chromaFormatConstraint = CHROMA_444; } } else if (chromaFormat == CHROMA_400) { if (bIntraConstraintFlag) { chromaFormatConstraint = CHROMA_420; // there is no intra 4:0:0 profile. bitDepthConstraint = trialBitDepthConstraint; } else { chromaFormatConstraint = CHROMA_400; bitDepthConstraint = trialBitDepthConstraint == 8 ? 8 : 12; } } else { bitDepthConstraint = trialBitDepthConstraint; chromaFormatConstraint = chromaFormat; if (bUsingChromaQPAdjustment && chromaFormat == CHROMA_420) { chromaFormatConstraint = CHROMA_422; // 4:2:0 cannot use the chroma qp tool. } if (chromaFormatConstraint == CHROMA_422 && bitDepthConstraint == 8) { bitDepthConstraint = 10; // there is no 8-bit 4:2:2 profile. } if (chromaFormatConstraint == CHROMA_420 && !bIntraConstraintFlag) { bitDepthConstraint = 12; // there is no 8 or 10-bit 4:2:0 inter RExt profile. } } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param argc number of arguments \param argv array of arguments \retval true when success */ Bool TAppEncCfg::parseCfg( Int argc, TChar* argv[] ) { Bool do_help = false; Int tmpChromaFormat; Int tmpInputChromaFormat; Int tmpConstraintChromaFormat; Int tmpWeightedPredictionMethod; Int tmpFastInterSearchMode; Int tmpMotionEstimationSearchMethod; Int tmpSliceMode; Int tmpSliceSegmentMode; Int tmpDecodedPictureHashSEIMappedType; string inputColourSpaceConvert; string inputPathPrefix; UIProfileName UIProfile; Int saoOffsetBitShift[MAX_NUM_CHANNEL_TYPE]; // Multi-value input fields: // minval, maxval (incl), min_entries, max_entries (incl) [, default values, number of default values] SMultiValueInput cfg_ColumnWidth (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_RowHeight (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_startOfCodedInterval (std::numeric_limits::min(), std::numeric_limits::max(), 0, 1<<16); SMultiValueInput cfg_codedPivotValue (std::numeric_limits::min(), std::numeric_limits::max(), 0, 1<<16); SMultiValueInput cfg_targetPivotValue (std::numeric_limits::min(), std::numeric_limits::max(), 0, 1<<16); SMultiValueInput cfg_adIntraLambdaModifier (0, std::numeric_limits::max(), 0, MAX_TLAYER); ///< Lambda modifier for Intra pictures, one for each temporal layer. If size>temporalLayer, then use [temporalLayer], else if size>0, use [size()-1], else use m_adLambdaModifier. const Int defaultLumaLevelTodQp_QpChangePoints[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6}; const Int defaultLumaLevelTodQp_LumaChangePoints[] = { 0, 301, 367, 434, 501, 567, 634, 701, 767, 834}; SMultiValueInput cfg_lumaLeveltoDQPMappingQP (-MAX_QP, MAX_QP, 0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_QpChangePoints, sizeof(defaultLumaLevelTodQp_QpChangePoints )/sizeof(Int)); SMultiValueInput cfg_lumaLeveltoDQPMappingLuma (0, std::numeric_limits::max(), 0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_LumaChangePoints, sizeof(defaultLumaLevelTodQp_LumaChangePoints)/sizeof(Int)); UInt lumaLevelToDeltaQPMode; const UInt defaultInputKneeCodes[3] = { 600, 800, 900 }; const UInt defaultOutputKneeCodes[3] = { 100, 250, 450 }; Int cfg_kneeSEINumKneePointsMinus1=0; SMultiValueInput cfg_kneeSEIInputKneePointValue (1, 999, 0, 999, defaultInputKneeCodes, sizeof(defaultInputKneeCodes )/sizeof(UInt)); SMultiValueInput cfg_kneeSEIOutputKneePointValue (0, 1000, 0, 999, defaultOutputKneeCodes, sizeof(defaultOutputKneeCodes)/sizeof(UInt)); const Int defaultPrimaryCodes[6] = { 0,50000, 0,0, 50000,0 }; const Int defaultWhitePointCode[2] = { 16667, 16667 }; SMultiValueInput cfg_DisplayPrimariesCode (0, 50000, 6, 6, defaultPrimaryCodes, sizeof(defaultPrimaryCodes )/sizeof(Int)); SMultiValueInput cfg_DisplayWhitePointCode (0, 50000, 2, 2, defaultWhitePointCode, sizeof(defaultWhitePointCode)/sizeof(Int)); SMultiValueInput cfg_timeCodeSeiTimeStampFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiNumUnitFieldBasedFlag(0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiCountingType (0, 6, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiFullTimeStampFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiDiscontinuityFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiCntDroppedFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiNumberOfFrames (0,511, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiSecondsValue (0, 59, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiMinutesValue (0, 59, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiHoursValue (0, 23, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiSecondsFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiMinutesFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiHoursFlag (0, 1, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiTimeOffsetLength (0, 31, 0, MAX_TIMECODE_SEI_SETS); SMultiValueInput cfg_timeCodeSeiTimeOffsetValue (std::numeric_limits::min(), std::numeric_limits::max(), 0, MAX_TIMECODE_SEI_SETS); #if JVET_X0048_X0103_FILM_GRAIN // default values used for FGC SEI parameter parsing SMultiValueInput cfg_FgcSEIIntensityIntervalLowerBoundComp[3]={SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256)}; SMultiValueInput cfg_FgcSEIIntensityIntervalUpperBoundComp[3]={SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256), SMultiValueInput (0, 255, 0, 256)}; SMultiValueInput cfg_FgcSEICompModelValueComp[3]={SMultiValueInput (0, 65535, 0, 256 * 6), SMultiValueInput (0, 65535, 0, 256 * 6), SMultiValueInput (0, 65535, 0, 256 * 6)}; #endif SMultiValueInput cfg_omniViewportSEIAzimuthCentre (-11796480, 11796479, 0, 15); SMultiValueInput cfg_omniViewportSEIElevationCentre ( -5898240, 5898240, 0, 15); SMultiValueInput cfg_omniViewportSEITiltCentre (-11796480, 11796479, 0, 15); SMultiValueInput cfg_omniViewportSEIHorRange ( 1, 23592960, 0, 15); SMultiValueInput cfg_omniViewportSEIVerRange ( 1, 11796480, 0, 15); SMultiValueInput cfg_rwpSEIRwpTransformType (0, 7, 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpGuardBandFlag (0, 1, 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIProjRegionWidth (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIProjRegionHeight (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpSEIProjRegionTop (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIProjRegionLeft (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIPackedRegionWidth (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIPackedRegionHeight (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIPackedRegionTop (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIPackedRegionLeft (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpLeftGuardBandWidth (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpRightGuardBandWidth (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpTopGuardBandHeight (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpBottomGuardBandHeight (0, std::numeric_limits::max(), 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpGuardBandNotUsedForPredFlag (0, 1, 0, std::numeric_limits::max()); SMultiValueInput cfg_rwpSEIRwpGuardBandType (0, 7, 0, 4*std::numeric_limits::max()); SMultiValueInput cfg_fviSEIFisheyeCircularRegionCentreX (0, std::numeric_limits::max(), 0, 4); // CONFIRM: all the '3's have been changed to '4's since "The value of fisheye_num_active_areas_minus1 shall be in the range of 0 to 3, inclusive", so up to 4 entries. SMultiValueInput cfg_fviSEIFisheyeCircularRegionCentreY (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeRectRegionTop (0, std::numeric_limits::max(), 0, 4); // do not know the height of the picture at this point, so cannot limit region top. SMultiValueInput cfg_fviSEIFisheyeRectRegionLeft (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeRectRegionWidth (1, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeRectRegionHeight (1, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeCircularRegionRadius (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeSceneRadius (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreAzimuth (-180*65536, 180*65536-1, 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreElevation ( -90*65536, 90*65536 , 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreTilt (-180*65536, 180*65536-1, 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreOffsetX (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreOffsetY (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeCameraCentreOffsetZ (0, std::numeric_limits::max(), 0, 4); SMultiValueInput cfg_fviSEIFisheyeFieldOfView (0, 360*65536, 0, 4); SMultiValueInput cfg_fviSEIFisheyeNumPolynomialCoeffs (0, 8, 0, 4); SMultiValueInput cfg_fviSEIFisheyePolynomialCoeff (std::numeric_limits::min(), std::numeric_limits::max(), 0, 4*8); UInt cfg_fviSEIFisheyeNumActiveAreasMinus1=0; #if SHUTTER_INTERVAL_SEI_MESSAGE SMultiValueInput cfg_siiSEIInputNumUnitsInSI (0, MAX_UINT, 0, 7); #endif Int warnUnknowParameter = 0; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("c", po::parseConfigFile, "configuration file name") ("WarnUnknowParameter,w", warnUnknowParameter, 0, "warn for unknown configuration parameters instead of failing") // File, I/O and source parameters ("InputFile,i", m_inputFileName, string(""), "Original YUV input file name") ("InputPathPrefix,-ipp", inputPathPrefix, string(""), "pathname to prepend to input filename") ("BitstreamFile,b", m_bitstreamFileName, string(""), "Bitstream output file name") ("ReconFile,o", m_reconFileName, string(""), "Reconstructed YUV output file name") #if SHUTTER_INTERVAL_SEI_PROCESSING ("SEIShutterIntervalPreFilename,-sii", m_shutterIntervalPreFileName, string(""), "File name of Pre-Filtering video. If empty, not output video\n") #endif ("SourceWidth,-wdt", m_sourceWidth, 0, "Source picture width") ("SourceHeight,-hgt", m_sourceHeight, 0, "Source picture height") ("InputBitDepth", m_inputBitDepth[CHANNEL_TYPE_LUMA], 8, "Bit-depth of input file") ("OutputBitDepth", m_outputBitDepth[CHANNEL_TYPE_LUMA], 0, "Bit-depth of output file (default:InternalBitDepth)") ("MSBExtendedBitDepth", m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA], 0, "bit depth of luma component after addition of MSBs of value 0 (used for synthesising High Dynamic Range source material). (default:InputBitDepth)") ("InternalBitDepth", m_internalBitDepth[CHANNEL_TYPE_LUMA], 0, "Bit-depth the codec operates at. (default:MSBExtendedBitDepth). If different to MSBExtendedBitDepth, source data will be converted") ("InputBitDepthC", m_inputBitDepth[CHANNEL_TYPE_CHROMA], 0, "As per InputBitDepth but for chroma component. (default:InputBitDepth)") ("OutputBitDepthC", m_outputBitDepth[CHANNEL_TYPE_CHROMA], 0, "As per OutputBitDepth but for chroma component. (default:InternalBitDepthC)") ("MSBExtendedBitDepthC", m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA], 0, "As per MSBExtendedBitDepth but for chroma component. (default:MSBExtendedBitDepth)") ("InternalBitDepthC", m_internalBitDepth[CHANNEL_TYPE_CHROMA], 0, "As per InternalBitDepth but for chroma component. (default:InternalBitDepth)") ("ExtendedPrecision", m_extendedPrecisionProcessingFlag, false, "Increased internal accuracies to support high bit depths (not valid in V1 profiles)") ("HighPrecisionPredictionWeighting", m_highPrecisionOffsetsEnabledFlag, false, "Use high precision option for weighted prediction (not valid in V1 profiles)") ("InputColourSpaceConvert", inputColourSpaceConvert, string(""), "Colour space conversion to apply to input video. Permitted values are (empty string=UNCHANGED) " + getListOfColourSpaceConverts(true)) ("SNRInternalColourSpace", m_snrInternalColourSpace, false, "If true, then no colour space conversion is applied prior to SNR, otherwise inverse of input is applied.") ("OutputInternalColourSpace", m_outputInternalColourSpace, false, "If true, then no colour space conversion is applied for reconstructed video, otherwise inverse of input is applied.") ("InputChromaFormat", tmpInputChromaFormat, 420, "InputChromaFormatIDC") ("MSEBasedSequencePSNR", m_printMSEBasedSequencePSNR, false, "0 (default) emit sequence PSNR only as a linear average of the frame PSNRs, 1 = also emit a sequence PSNR based on an average of the frame MSEs") ("PrintHexPSNR", m_printHexPsnr, false, "0 (default) don't emit hexadecimal PSNR for each frame, 1 = also emit hexadecimal PSNR values") ("PrintFrameMSE", m_printFrameMSE, false, "0 (default) emit only bit count and PSNRs for each frame, 1 = also emit MSE values") ("PrintSequenceMSE", m_printSequenceMSE, false, "0 (default) emit only bit rate and PSNRs for the whole sequence, 1 = also emit MSE values") ("PrintMSSSIM", m_printMSSSIM, false, "0 (default) do not print MS-SSIM scores, 1 = print MS-SSIM scores for each frame and for the whole sequence") ("xPSNREnableFlag,-xPS", m_bXPSNREnableFlag, false, "Cross-Component xPSNR computation") ("xPSNRYWeight,-xPS0", m_dXPSNRWeight[COMPONENT_Y], ( Double )1.0, "xPSNR weighting factor for Y (default: 1.0)") ("xPSNRCbWeight,-xPS1", m_dXPSNRWeight[COMPONENT_Cb], ( Double )1.0, "xPSNR weighting factor for Cb (default: 1.0)") ("xPSNRCrWeight,-xPS2", m_dXPSNRWeight[COMPONENT_Cr], ( Double )1.0, "xPSNR weighting factor for Cr (default: 1.0)") ("CabacZeroWordPaddingEnabled", m_cabacZeroWordPaddingEnabled, true, "0 do not add conforming cabac-zero-words to bit streams, 1 (default) = add cabac-zero-words as required") ("ChromaFormatIDC,-cf", tmpChromaFormat, 0, "ChromaFormatIDC (400|420|422|444 or set 0 (default) for same as InputChromaFormat)") ("ConformanceWindowMode", m_conformanceWindowMode, 0, "Window conformance mode (0: no window, 1:automatic padding, 2:padding parameters specified, 3:conformance window parameters specified") ("HorizontalPadding,-pdx", m_sourcePadding[0], 0, "Horizontal source padding for conformance window mode 2") ("VerticalPadding,-pdy", m_sourcePadding[1], 0, "Vertical source padding for conformance window mode 2") ("ConfWinLeft", m_confWinLeft, 0, "Left offset for window conformance mode 3") ("ConfWinRight", m_confWinRight, 0, "Right offset for window conformance mode 3") ("ConfWinTop", m_confWinTop, 0, "Top offset for window conformance mode 3") ("ConfWinBottom", m_confWinBottom, 0, "Bottom offset for window conformance mode 3") ("AccessUnitDelimiter", m_AccessUnitDelimiter, false, "Enable Access Unit Delimiter NALUs") ("FrameRate,-fr", m_iFrameRate, 0, "Frame rate") ("FrameSkip,-fs", m_FrameSkip, 0u, "Number of frames to skip at start of input YUV") ("TemporalSubsampleRatio,-ts", m_temporalSubsampleRatio, 1u, "Temporal sub-sample ratio when reading input YUV") ("FramesToBeEncoded,f", m_framesToBeEncoded, 0, "Number of frames to be encoded (default=all)") ("ClipInputVideoToRec709Range", m_bClipInputVideoToRec709Range, false, "If true then clip input video to the Rec. 709 Range on loading when InternalBitDepth is less than MSBExtendedBitDepth") ("ClipOutputVideoToRec709Range", m_bClipOutputVideoToRec709Range, false, "If true then clip output video to the Rec. 709 Range on saving when OutputBitDepth is less than InternalBitDepth") ("SummaryOutFilename", m_summaryOutFilename, string(), "Filename to use for producing summary output file. If empty, do not produce a file.") ("SummaryPicFilenameBase", m_summaryPicFilenameBase, string(), "Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended. If empty, do not produce a file.") ("SummaryVerboseness", m_summaryVerboseness, 0u, "Specifies the level of the verboseness of the text output") //Field coding parameters ("FieldCoding", m_isField, false, "Signals if it's a field based coding") ("TopFieldFirst, Tff", m_isTopFieldFirst, false, "In case of field based coding, signals whether if it's a top field first or not") ("EfficientFieldIRAPEnabled", m_bEfficientFieldIRAPEnabled, true, "Enable to code fields in a specific, potentially more efficient, order.") ("HarmonizeGopFirstFieldCoupleEnabled", m_bHarmonizeGopFirstFieldCoupleEnabled, true, "Enables harmonization of Gop first field couple") // Profile and level ("Profile", UIProfile, UI_NONE, "Profile name to use for encoding. Use main (for main), main10 (for main10), main-still-picture, main-RExt (for Range Extensions profile), any of the RExt specific profile names, or none") ("Level", m_level, Level::NONE, "Level limit to be used, eg 5.1, or none") ("Tier", m_levelTier, Level::MAIN, "Tier to use for interpretation of --Level (main or high only)") ("MaxBitDepthConstraint", m_bitDepthConstraint, 0u, "Bit depth to use for profile-constraint for RExt profiles. 0=automatically choose based upon other parameters") ("MaxChromaFormatConstraint", tmpConstraintChromaFormat, 0, "Chroma-format to use for the profile-constraint for RExt profiles. 0=automatically choose based upon other parameters") ("IntraConstraintFlag", m_intraConstraintFlag, false, "Value of general_intra_constraint_flag to use for RExt profiles (not used if an explicit RExt sub-profile is specified)") ("OnePictureOnlyConstraintFlag", m_onePictureOnlyConstraintFlag, false, "Value of general_one_picture_only_constraint_flag to use for RExt profiles (not used if an explicit RExt sub-profile is specified)") ("LowerBitRateConstraintFlag", m_lowerBitRateConstraintFlag, true, "Value of general_lower_bit_rate_constraint_flag to use for RExt profiles") ("ProgressiveSource", m_progressiveSourceFlag, false, "Indicate that source is progressive") ("InterlacedSource", m_interlacedSourceFlag, false, "Indicate that source is interlaced") ("NonPackedSource", m_nonPackedConstraintFlag, false, "Indicate that source does not contain frame packing") ("FrameOnly", m_frameOnlyConstraintFlag, false, "Indicate that the bitstream contains only frames") // Unit definition parameters ("MaxCUWidth", m_uiMaxCUWidth, 64u) ("MaxCUHeight", m_uiMaxCUHeight, 64u) // todo: remove defaults from MaxCUSize ("MaxCUSize,s", m_uiMaxCUWidth, 64u, "Maximum CU size") ("MaxCUSize,s", m_uiMaxCUHeight, 64u, "Maximum CU size") ("MaxPartitionDepth,h", m_uiMaxCUDepth, 4u, "CU depth") ("QuadtreeTULog2MaxSize", m_uiQuadtreeTULog2MaxSize, 6u, "Maximum TU size in logarithm base 2") ("QuadtreeTULog2MinSize", m_uiQuadtreeTULog2MinSize, 2u, "Minimum TU size in logarithm base 2") ("QuadtreeTUMaxDepthIntra", m_uiQuadtreeTUMaxDepthIntra, 1u, "Depth of TU tree for intra CUs") ("QuadtreeTUMaxDepthInter", m_uiQuadtreeTUMaxDepthInter, 2u, "Depth of TU tree for inter CUs") // Coding structure paramters ("IntraPeriod,-ip", m_iIntraPeriod, -1, "Intra period in frames, (-1: only first frame)") ("DecodingRefreshType,-dr", m_iDecodingRefreshType, 0, "Intra refresh type (0:none 1:CRA 2:IDR 3:RecPointSEI)") ("GOPSize,g", m_iGOPSize, 1, "GOP size of temporal structure") ("ReWriteParamSetsFlag", m_bReWriteParamSetsFlag, true, "Enable rewriting of Parameter sets before every (intra) random access point") // motion search options ("DisableIntraInInter", m_bDisableIntraPUsInInterSlices, false, "Flag to disable intra PUs in inter slices") ("FastSearch", tmpMotionEstimationSearchMethod, Int(MESEARCH_DIAMOND), "0:Full search 1:Diamond 2:Selective 3:Enhanced Diamond") ("SearchRange,-sr", m_iSearchRange, 96, "Motion search range") ("BipredSearchRange", m_bipredSearchRange, 4, "Motion search range for bipred refinement") ("MinSearchWindow", m_minSearchWindow, 8, "Minimum motion search window size for the adaptive window ME") ("RestrictMESampling", m_bRestrictMESampling, false, "Restrict ME Sampling for selective inter motion search") ("ClipForBiPredMEEnabled", m_bClipForBiPredMeEnabled, false, "Enables clipping in the Bi-Pred ME. It is disabled to reduce encoder run-time") ("FastMEAssumingSmootherMVEnabled", m_bFastMEAssumingSmootherMVEnabled, true, "Enables fast ME assuming a smoother MV.") ("HadamardME", m_bUseHADME, true, "Hadamard ME for fractional-pel") ("ASR", m_bUseASR, false, "Adaptive motion search range"); opts.addOptions() // Mode decision parameters ("LambdaModifier0,-LM0", m_adLambdaModifier[ 0 ], ( Double )1.0, "Lambda modifier for temporal layer 0. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier1,-LM1", m_adLambdaModifier[ 1 ], ( Double )1.0, "Lambda modifier for temporal layer 1. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier2,-LM2", m_adLambdaModifier[ 2 ], ( Double )1.0, "Lambda modifier for temporal layer 2. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier3,-LM3", m_adLambdaModifier[ 3 ], ( Double )1.0, "Lambda modifier for temporal layer 3. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier4,-LM4", m_adLambdaModifier[ 4 ], ( Double )1.0, "Lambda modifier for temporal layer 4. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier5,-LM5", m_adLambdaModifier[ 5 ], ( Double )1.0, "Lambda modifier for temporal layer 5. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifier6,-LM6", m_adLambdaModifier[ 6 ], ( Double )1.0, "Lambda modifier for temporal layer 6. If LambdaModifierI is used, this will not affect intra pictures") ("LambdaModifierI,-LMI", cfg_adIntraLambdaModifier, cfg_adIntraLambdaModifier, "Lambda modifiers for Intra pictures, comma separated, up to one the number of temporal layer. If entry for temporalLayer exists, then use it, else if some are specified, use the last, else use the standard LambdaModifiers.") ("IQPFactor,-IQF", m_dIntraQpFactor, -1.0, "Intra QP Factor for Lambda Computation. If negative, the default will scale lambda based on GOP size (unless LambdaFromQpEnable then IntraQPOffset is used instead)") /* Quantization parameters */ ("QP,q", m_iQP, 30, "Qp value") ("QPIncrementFrame,-qpif", m_qpIncrementAtSourceFrame, OptionalValue(), "If a source file frame number is specified, the internal QP will be incremented for all POCs associated with source frames >= frame number. If empty, do not increment.") ("IntraQPOffset", m_intraQPOffset, 0, "Qp offset value for intra slice, typically determined based on GOP size") ("LambdaFromQpEnable", m_lambdaFromQPEnable, false, "Enable flag for derivation of lambda from QP") ("DeltaQpRD,-dqr", m_uiDeltaQpRD, 0u, "max dQp offset for slice") ("MaxDeltaQP,d", m_iMaxDeltaQP, 0, "max dQp offset for block") ("MaxCuDQPDepth,-dqd", m_iMaxCuDQPDepth, 0, "max depth for a minimum CuDQP") ("MaxCUChromaQpAdjustmentDepth", m_diffCuChromaQpOffsetDepth, -1, "Maximum depth for CU chroma Qp adjustment - set less than 0 to disable") ("FastDeltaQP", m_bFastDeltaQP, false, "Fast Delta QP Algorithm") ("LumaLevelToDeltaQPMode", lumaLevelToDeltaQPMode, 0u, "Luma based Delta QP 0(default): not used. 1: Based on CTU average, 2: Based on Max luma in CTU") ("LumaLevelToDeltaQPMaxValWeight", m_lumaLevelToDeltaQPMapping.maxMethodWeight, 1.0, "Weight of block max luma val when LumaLevelToDeltaQPMode = 2") ("LumaLevelToDeltaQPMappingLuma", cfg_lumaLeveltoDQPMappingLuma, cfg_lumaLeveltoDQPMappingLuma, "Luma to Delta QP Mapping - luma thresholds") ("LumaLevelToDeltaQPMappingDQP", cfg_lumaLeveltoDQPMappingQP, cfg_lumaLeveltoDQPMappingQP, "Luma to Delta QP Mapping - DQP values") ("CbQpOffset,-cbqpofs", m_cbQpOffset, 0, "Chroma Cb QP Offset") ("CrQpOffset,-crqpofs", m_crQpOffset, 0, "Chroma Cr QP Offset") ("WCGPPSEnable", m_wcgChromaQpControl.enabled, false, "1: Enable the WCG PPS chroma modulation scheme. 0 (default) disabled") ("WCGPPSCbQpScale", m_wcgChromaQpControl.chromaCbQpScale, 1.0, "WCG PPS Chroma Cb QP Scale") ("WCGPPSCrQpScale", m_wcgChromaQpControl.chromaCrQpScale, 1.0, "WCG PPS Chroma Cr QP Scale") ("WCGPPSChromaQpScale", m_wcgChromaQpControl.chromaQpScale, 0.0, "WCG PPS Chroma QP Scale") ("WCGPPSChromaQpOffset", m_wcgChromaQpControl.chromaQpOffset, 0.0, "WCG PPS Chroma QP Offset") ("SliceChromaQPOffsetPeriodicity", m_sliceChromaQpOffsetPeriodicity, 0u, "Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature.") ("SliceCbQpOffsetIntraOrPeriodic", m_sliceChromaQpOffsetIntraOrPeriodic[0], 0, "Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table.") ("SliceCrQpOffsetIntraOrPeriodic", m_sliceChromaQpOffsetIntraOrPeriodic[1], 0, "Chroma Cr QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table.") #if ADAPTIVE_QP_SELECTION ("AdaptiveQpSelection,-aqps", m_bUseAdaptQpSelect, false, "AdaptiveQpSelection") #endif #if JVET_V0078 ("SmoothQPReductionEnable", m_bSmoothQPReductionEnable, false, "Enable QP reduction for smooth blocks according to: Clip3(SmoothQPReductionLimit, 0, SmoothQPReductionModelScale*baseQP+SmoothQPReductionModelOffset)") ("SmoothQPReductionThreshold", m_dSmoothQPReductionThreshold, 3.0, "Threshold parameter for smoothness (SmoothQPReductionThreshold * number of samples in block)") ("SmoothQPReductionModelScale", m_dSmoothQPReductionModelScale, -1.0, "Scale parameter of the QP reduction model") ("SmoothQPReductionModelOffset", m_dSmoothQPReductionModelOffset, 27.0, "Offset parameter of the QP reduction model") ("SmoothQPReductionLimit", m_iSmoothQPReductionLimit, -16, "Threshold parameter for controlling maximum amount of QP reduction by the QP reduction model") ("SmoothQPReductionPeriodicity", m_iSmoothQPReductionPeriodicity, 1, "Periodicity parameter of the QP reduction model, 1: all frames, 0: only intra pictures, 2: every second frame, etc") #endif #if JVET_Y0077_BIM ("BIM", m_bimEnabled, false, "Block Importance Mapping QP adaptation depending on estimated propagation of reference samples.") #endif ("AdaptiveQP,-aq", m_bUseAdaptiveQP, false, "QP adaptation based on a psycho-visual model") ("MaxQPAdaptationRange,-aqr", m_iQPAdaptationRange, 6, "QP adaptation range") ("dQPFile,m", m_dQPFileName, string(""), "dQP file name") ("RDOQ", m_useRDOQ, true) ("RDOQTS", m_useRDOQTS, true) ("SelectiveRDOQ", m_useSelectiveRDOQ, false, "Enable selective RDOQ") ("RDpenalty", m_rdPenalty, 0, "RD-penalty for 32x32 TU for intra in non-intra slices. 0:disabled 1:RD-penalty 2:maximum RD-penalty") // Deblocking filter parameters ("LoopFilterDisable", m_bLoopFilterDisable, false) ("LoopFilterOffsetInPPS", m_loopFilterOffsetInPPS, true) ("LoopFilterBetaOffset_div2", m_loopFilterBetaOffsetDiv2, 0) ("LoopFilterTcOffset_div2", m_loopFilterTcOffsetDiv2, 0) ("DeblockingFilterMetric", m_deblockingFilterMetric, 0) // Coding tools ("AMP", m_enableAMP, true, "Enable asymmetric motion partitions") ("CrossComponentPrediction", m_crossComponentPredictionEnabledFlag, false, "Enable the use of cross-component prediction (not valid in V1 profiles)") ("ReconBasedCrossCPredictionEstimate", m_reconBasedCrossCPredictionEstimate, false, "When determining the alpha value for cross-component prediction, use the decoded residual rather than the pre-transform encoder-side residual") ("SaoLumaOffsetBitShift", saoOffsetBitShift[CHANNEL_TYPE_LUMA], 0, "Specify the luma SAO bit-shift. If negative, automatically calculate a suitable value based upon bit depth and initial QP") ("SaoChromaOffsetBitShift", saoOffsetBitShift[CHANNEL_TYPE_CHROMA], 0, "Specify the chroma SAO bit-shift. If negative, automatically calculate a suitable value based upon bit depth and initial QP") ("TransformSkip", m_useTransformSkip, false, "Intra transform skipping") ("TransformSkipFast", m_useTransformSkipFast, false, "Fast intra transform skipping") ("TransformSkipLog2MaxSize", m_log2MaxTransformSkipBlockSize, 2U, "Specify transform-skip maximum size. Minimum 2. (not valid in V1 profiles)") ("ImplicitResidualDPCM", m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT], false, "Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles)") ("ExplicitResidualDPCM", m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT], false, "Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles)") ("ResidualRotation", m_transformSkipRotationEnabledFlag, false, "Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles)") ("SingleSignificanceMapContext", m_transformSkipContextEnabledFlag, false, "Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles)") ("GolombRiceParameterAdaptation", m_persistentRiceAdaptationEnabledFlag, false, "Enable the adaptation of the Golomb-Rice parameter over the course of each slice") ("AlignCABACBeforeBypass", m_cabacBypassAlignmentEnabledFlag, false, "Align the CABAC engine to a defined fraction of a bit prior to coding bypass data. Must be 1 in high bit rate profile, 0 otherwise" ) ("SAO", m_bUseSAO, true, "Enable Sample Adaptive Offset") ("TestSAODisableAtPictureLevel", m_bTestSAODisableAtPictureLevel, false, "Enables the testing of disabling SAO at the picture level after having analysed all blocks") ("SaoEncodingRate", m_saoEncodingRate, 0.75, "When >0 SAO early picture termination is enabled for luma and chroma") ("SaoEncodingRateChroma", m_saoEncodingRateChroma, 0.5, "The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma") ("MaxNumOffsetsPerPic", m_maxNumOffsetsPerPic, 2048, "Max number of SAO offset per picture (Default: 2048)") ("SAOLcuBoundary", m_saoCtuBoundary, false, "0: right/bottom CTU boundary areas skipped from SAO parameter estimation, 1: non-deblocked pixels are used for those areas") ("ResetEncoderStateAfterIRAP", m_resetEncoderStateAfterIRAP, true, "When true, resets the encoder's decisions after an IRAP (POC order). Enabled by default.") ("SliceMode", tmpSliceMode, Int(NO_SLICES), "0: Disable all Recon slice limits, 1: Enforce max # of CTUs, 2: Enforce max # of bytes, 3:specify tiles per dependent slice") ("SliceArgument", m_sliceArgument, 0, "Depending on SliceMode being:" "\t1: max number of CTUs per slice" "\t2: max number of bytes per slice" "\t3: max number of tiles per slice") ("SliceSegmentMode", tmpSliceSegmentMode, Int(NO_SLICES), "0: Disable all slice segment limits, 1: Enforce max # of CTUs, 2: Enforce max # of bytes, 3:specify tiles per dependent slice") ("SliceSegmentArgument", m_sliceSegmentArgument, 0, "Depending on SliceSegmentMode being:" "\t1: max number of CTUs per slice segment" "\t2: max number of bytes per slice segment" "\t3: max number of tiles per slice segment") ("LFCrossSliceBoundaryFlag", m_bLFCrossSliceBoundaryFlag, true) ("ConstrainedIntraPred", m_bUseConstrainedIntraPred, false, "Constrained Intra Prediction") ("FastUDIUseMPMEnabled", m_bFastUDIUseMPMEnabled, true, "If enabled, adapt intra direction search, accounting for MPM") ("FastMEForGenBLowDelayEnabled", m_bFastMEForGenBLowDelayEnabled, true, "If enabled use a fast ME for generalised B Low Delay slices") ("UseBLambdaForNonKeyLowDelayPictures", m_bUseBLambdaForNonKeyLowDelayPictures, true, "Enables use of B-Lambda for non-key low-delay pictures") ("PCMEnabledFlag", m_usePCM, false) ("PCMLog2MaxSize", m_pcmLog2MaxSize, 5u) ("PCMLog2MinSize", m_uiPCMLog2MinSize, 3u) ("PCMInputBitDepthFlag", m_bPCMInputBitDepthFlag, true) ("PCMFilterDisableFlag", m_bPCMFilterDisableFlag, false) ("IntraReferenceSmoothing", m_enableIntraReferenceSmoothing, true, "0: Disable use of intra reference smoothing (not valid in V1 profiles). 1: Enable use of intra reference smoothing (same as V1)") ("WeightedPredP,-wpP", m_useWeightedPred, false, "Use weighted prediction in P slices") ("WeightedPredB,-wpB", m_useWeightedBiPred, false, "Use weighted (bidirectional) prediction in B slices") ("WeightedPredMethod,-wpM", tmpWeightedPredictionMethod, Int(WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT), "Weighted prediction method") ("Log2ParallelMergeLevel", m_log2ParallelMergeLevel, 2u, "Parallel merge estimation region") //deprecated copies of renamed tile parameters ("UniformSpacingIdc", m_tileUniformSpacingFlag, false, "deprecated alias of TileUniformSpacing") ("ColumnWidthArray", cfg_ColumnWidth, cfg_ColumnWidth, "deprecated alias of TileColumnWidthArray") ("RowHeightArray", cfg_RowHeight, cfg_RowHeight, "deprecated alias of TileRowHeightArray") ("TileUniformSpacing", m_tileUniformSpacingFlag, false, "Indicates that tile columns and rows are distributed uniformly") ("NumTileColumnsMinus1", m_numTileColumnsMinus1, 0, "Number of tile columns in a picture minus 1") ("NumTileRowsMinus1", m_numTileRowsMinus1, 0, "Number of rows in a picture minus 1") ("TileColumnWidthArray", cfg_ColumnWidth, cfg_ColumnWidth, "Array containing tile column width values in units of CTU") ("TileRowHeightArray", cfg_RowHeight, cfg_RowHeight, "Array containing tile row height values in units of CTU") ("LFCrossTileBoundaryFlag", m_bLFCrossTileBoundaryFlag, true, "1: cross-tile-boundary loop filtering. 0:non-cross-tile-boundary loop filtering") ("WaveFrontSynchro", m_entropyCodingSyncEnabledFlag, false, "0: entropy coding sync disabled; 1 entropy coding sync enabled") ("ScalingList", m_useScalingListId, SCALING_LIST_OFF, "0/off: no scaling list, 1/default: default scaling lists, 2/file: scaling lists specified in ScalingListFile") ("ScalingListFile", m_scalingListFileName, string(""), "Scaling list file name. Use an empty string to produce help.") ("SignHideFlag,-SBH", m_signDataHidingEnabledFlag, true) ("MaxNumMergeCand", m_maxNumMergeCand, 5u, "Maximum number of merge candidates") /* Misc. */ ("SEIDecodedPictureHash", tmpDecodedPictureHashSEIMappedType, 0, "Control generation of decode picture hash SEI messages\n" "\t3: checksum\n" "\t2: CRC\n" "\t1: use MD5\n" "\t0: disable") ("TMVPMode", m_TMVPModeId, 1, "TMVP mode 0: TMVP disable for all slices. 1: TMVP enable for all slices (default) 2: TMVP enable for certain slices only") ("FEN", tmpFastInterSearchMode, Int(FASTINTERSEARCH_DISABLED), "fast encoder setting") ("ECU", m_bUseEarlyCU, false, "Early CU setting") ("FDM", m_useFastDecisionForMerge, true, "Fast decision for Merge RD Cost") ("CFM", m_bUseCbfFastMode, false, "Cbf fast mode setting") ("ESD", m_useEarlySkipDetection, false, "Early SKIP detection setting") ( "RateControl", m_RCEnableRateControl, false, "Rate control: enable rate control" ) ( "TargetBitrate", m_RCTargetBitrate, 0, "Rate control: target bit-rate" ) ( "KeepHierarchicalBit", m_RCKeepHierarchicalBit, 0, "Rate control: 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation" ) ( "LCULevelRateControl", m_RCLCULevelRC, true, "Rate control: true: CTU level RC; false: picture level RC" ) ( "RCLCUSeparateModel", m_RCUseLCUSeparateModel, true, "Rate control: use CTU level separate R-lambda model" ) ( "InitialQP", m_RCInitialQP, 0, "Rate control: initial QP" ) ( "RCForceIntraQP", m_RCForceIntraQP, false, "Rate control: force intra QP to be equal to initial QP" ) ( "RCCpbSaturation", m_RCCpbSaturationEnabled, false, "Rate control: enable target bits saturation to avoid CPB overflow and underflow" ) ( "RCCpbSize", m_RCCpbSize, 0u, "Rate control: CPB size" ) ( "RCInitialCpbFullness", m_RCInitialCpbFullness, 0.9, "Rate control: initial CPB fullness" ) ("TransquantBypassEnable", m_TransquantBypassEnabledFlag, false, "transquant_bypass_enabled_flag indicator in PPS") ("TransquantBypassEnableFlag", m_TransquantBypassEnabledFlag, false, "deprecated alias for TransquantBypassEnable") ("CUTransquantBypassFlagForce", m_CUTransquantBypassFlagForce, false, "Force transquant bypass mode, when transquant_bypass_enabled_flag is enabled") ("CostMode", m_costMode, COST_STANDARD_LOSSY, "Use alternative cost functions: choose between 'lossy', 'sequence_level_lossless', 'lossless' (which forces QP to " MACRO_TO_STRING(LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP) ") and 'mixed_lossless_lossy' (which used QP'=" MACRO_TO_STRING(LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME) " for pre-estimates of transquant-bypass blocks).") ("RecalculateQPAccordingToLambda", m_recalculateQPAccordingToLambda, false, "Recalculate QP values according to lambda values. Do not suggest to be enabled in all intra case") ("StrongIntraSmoothing,-sis", m_useStrongIntraSmoothing, true, "Enable strong intra smoothing for 32x32 blocks") ("SEIActiveParameterSets", m_activeParameterSetsSEIEnabled, 0, "Enable generation of active parameter sets SEI messages"); opts.addOptions() ("VuiParametersPresent,-vui", m_vuiParametersPresentFlag, false, "Enable generation of vui_parameters()") ("AspectRatioInfoPresent", m_aspectRatioInfoPresentFlag, false, "Signals whether aspect_ratio_idc is present") ("AspectRatioIdc", m_aspectRatioIdc, 0, "aspect_ratio_idc") ("SarWidth", m_sarWidth, 0, "horizontal size of the sample aspect ratio") ("SarHeight", m_sarHeight, 0, "vertical size of the sample aspect ratio") ("OverscanInfoPresent", m_overscanInfoPresentFlag, false, "Indicates whether conformant decoded pictures are suitable for display using overscan\n") ("OverscanAppropriate", m_overscanAppropriateFlag, false, "Indicates whether conformant decoded pictures are suitable for display using overscan\n") ("VideoSignalTypePresent", m_videoSignalTypePresentFlag, false, "Signals whether video_format, video_full_range_flag, and colour_description_present_flag are present") ("VideoFormat", m_videoFormat, 5, "Indicates representation of pictures") ("VideoFullRange", m_videoFullRangeFlag, false, "Indicates the black level and range of luma and chroma signals") ("ColourDescriptionPresent", m_colourDescriptionPresentFlag, false, "Signals whether colour_primaries, transfer_characteristics and matrix_coefficients are present") ("ColourPrimaries", m_colourPrimaries, 2, "Indicates chromaticity coordinates of the source primaries") ("TransferCharacteristics", m_transferCharacteristics, 2, "Indicates the opto-electronic transfer characteristics of the source") ("MatrixCoefficients", m_matrixCoefficients, 2, "Describes the matrix coefficients used in deriving luma and chroma from RGB primaries") ("ChromaLocInfoPresent", m_chromaLocInfoPresentFlag, false, "Signals whether chroma_sample_loc_type_top_field and chroma_sample_loc_type_bottom_field are present") ("ChromaSampleLocTypeTopField", m_chromaSampleLocTypeTopField, 0, "Specifies the location of chroma samples for top field") ("ChromaSampleLocTypeBottomField", m_chromaSampleLocTypeBottomField, 0, "Specifies the location of chroma samples for bottom field") ("NeutralChromaIndication", m_neutralChromaIndicationFlag, false, "Indicates that the value of all decoded chroma samples is equal to 1<<(BitDepthCr-1)") ("DefaultDisplayWindowFlag", m_defaultDisplayWindowFlag, false, "Indicates the presence of the Default Window parameters") ("DefDispWinLeftOffset", m_defDispWinLeftOffset, 0, "Specifies the left offset of the default display window from the conformance window") ("DefDispWinRightOffset", m_defDispWinRightOffset, 0, "Specifies the right offset of the default display window from the conformance window") ("DefDispWinTopOffset", m_defDispWinTopOffset, 0, "Specifies the top offset of the default display window from the conformance window") ("DefDispWinBottomOffset", m_defDispWinBottomOffset, 0, "Specifies the bottom offset of the default display window from the conformance window") ("FrameFieldInfoPresentFlag", m_frameFieldInfoPresentFlag, false, "Indicates that pic_struct and field coding related values are present in picture timing SEI messages") ("PocProportionalToTimingFlag", m_pocProportionalToTimingFlag, false, "Indicates that the POC value is proportional to the output time w.r.t. first picture in CVS") ("NumTicksPocDiffOneMinus1", m_numTicksPocDiffOneMinus1, 0, "Number of ticks minus 1 that for a POC difference of one") ("BitstreamRestriction", m_bitstreamRestrictionFlag, false, "Signals whether bitstream restriction parameters are present") ("TilesFixedStructure", m_tilesFixedStructureFlag, false, "Indicates that each active picture parameter set has the same values of the syntax elements related to tiles") ("MotionVectorsOverPicBoundaries", m_motionVectorsOverPicBoundariesFlag, false, "Indicates that no samples outside the picture boundaries are used for inter prediction") ("MaxBytesPerPicDenom", m_maxBytesPerPicDenom, 2, "Indicates a number of bytes not exceeded by the sum of the sizes of the VCL NAL units associated with any coded picture") ("MaxBitsPerMinCuDenom", m_maxBitsPerMinCuDenom, 1, "Indicates an upper bound for the number of bits of coding_unit() data") ("Log2MaxMvLengthHorizontal", m_log2MaxMvLengthHorizontal, 15, "Indicate the maximum absolute value of a decoded horizontal MV component in quarter-pel luma units") ("Log2MaxMvLengthVertical", m_log2MaxMvLengthVertical, 15, "Indicate the maximum absolute value of a decoded vertical MV component in quarter-pel luma units"); opts.addOptions() ("SEIColourRemappingInfoFileRoot,-cri", m_colourRemapSEIFileRoot, string(""), "Colour Remapping Information SEI parameters root file name (wo num ext); only the file name base is to be added. Underscore and POC would be automatically addded to . E.g. \"-cri cri\" will search for files cri_0.txt, cri_1.txt, ...") ("SEIRecoveryPoint", m_recoveryPointSEIEnabled, false, "Control generation of recovery point SEI messages") ("SEIBufferingPeriod", m_bufferingPeriodSEIEnabled, false, "Control generation of buffering period SEI messages") ("SEIPictureTiming", m_pictureTimingSEIEnabled, false, "Control generation of picture timing SEI messages") ("SEIToneMappingInfo", m_toneMappingInfoSEIEnabled, false, "Control generation of Tone Mapping SEI messages") ("SEIToneMapId", m_toneMapId, 0, "Specifies Id of Tone Mapping SEI message for a given session") ("SEIToneMapCancelFlag", m_toneMapCancelFlag, false, "Indicates that Tone Mapping SEI message cancels the persistence or follows") ("SEIToneMapPersistenceFlag", m_toneMapPersistenceFlag, true, "Specifies the persistence of the Tone Mapping SEI message") ("SEIToneMapCodedDataBitDepth", m_toneMapCodedDataBitDepth, 8, "Specifies Coded Data BitDepth of Tone Mapping SEI messages") ("SEIToneMapTargetBitDepth", m_toneMapTargetBitDepth, 8, "Specifies Output BitDepth of Tone mapping function") ("SEIToneMapModelId", m_toneMapModelId, 0, "Specifies Model utilized for mapping coded data into target_bit_depth range\n" "\t0: linear mapping with clipping\n" "\t1: sigmoidal mapping\n" "\t2: user-defined table mapping\n" "\t3: piece-wise linear mapping\n" "\t4: luminance dynamic range information ") ("SEIToneMapMinValue", m_toneMapMinValue, 0, "Specifies the minimum value in mode 0") ("SEIToneMapMaxValue", m_toneMapMaxValue, 1023, "Specifies the maximum value in mode 0") ("SEIToneMapSigmoidMidpoint", m_sigmoidMidpoint, 512, "Specifies the centre point in mode 1") ("SEIToneMapSigmoidWidth", m_sigmoidWidth, 960, "Specifies the distance between 5% and 95% values of the target_bit_depth in mode 1") ("SEIToneMapStartOfCodedInterval", cfg_startOfCodedInterval, cfg_startOfCodedInterval, "Array of user-defined mapping table") ("SEIToneMapNumPivots", m_numPivots, 0, "Specifies the number of pivot points in mode 3") ("SEIToneMapCodedPivotValue", cfg_codedPivotValue, cfg_codedPivotValue, "Array of pivot point") ("SEIToneMapTargetPivotValue", cfg_targetPivotValue, cfg_targetPivotValue, "Array of pivot point") ("SEIToneMapCameraIsoSpeedIdc", m_cameraIsoSpeedIdc, 0, "Indicates the camera ISO speed for daylight illumination") ("SEIToneMapCameraIsoSpeedValue", m_cameraIsoSpeedValue, 400, "Specifies the camera ISO speed for daylight illumination of Extended_ISO") ("SEIToneMapExposureIndexIdc", m_exposureIndexIdc, 0, "Indicates the exposure index setting of the camera") ("SEIToneMapExposureIndexValue", m_exposureIndexValue, 400, "Specifies the exposure index setting of the camera of Extended_ISO") ("SEIToneMapExposureCompensationValueSignFlag", m_exposureCompensationValueSignFlag, false, "Specifies the sign of ExposureCompensationValue") ("SEIToneMapExposureCompensationValueNumerator", m_exposureCompensationValueNumerator, 0, "Specifies the numerator of ExposureCompensationValue") ("SEIToneMapExposureCompensationValueDenomIdc", m_exposureCompensationValueDenomIdc, 2, "Specifies the denominator of ExposureCompensationValue") ("SEIToneMapRefScreenLuminanceWhite", m_refScreenLuminanceWhite, 350, "Specifies reference screen brightness setting in units of candela per square metre") ("SEIToneMapExtendedRangeWhiteLevel", m_extendedRangeWhiteLevel, 800, "Indicates the luminance dynamic range") ("SEIToneMapNominalBlackLevelLumaCodeValue", m_nominalBlackLevelLumaCodeValue, 16, "Specifies luma sample value of the nominal black level assigned decoded pictures") ("SEIToneMapNominalWhiteLevelLumaCodeValue", m_nominalWhiteLevelLumaCodeValue, 235, "Specifies luma sample value of the nominal white level assigned decoded pictures") ("SEIToneMapExtendedWhiteLevelLumaCodeValue", m_extendedWhiteLevelLumaCodeValue, 300, "Specifies luma sample value of the extended dynamic range assigned decoded pictures") ("SEIChromaResamplingFilterHint", m_chromaResamplingFilterSEIenabled, false, "Control generation of the chroma sampling filter hint SEI message") ("SEIChromaResamplingHorizontalFilterType", m_chromaResamplingHorFilterIdc, 2, "Defines the Index of the chroma sampling horizontal filter\n" "\t0: unspecified - Chroma filter is unknown or is determined by the application" "\t1: User-defined - Filter coefficients are specified in the chroma sampling filter hint SEI message" "\t2: Standards-defined - ITU-T Rec. T.800 | ISO/IEC15444-1, 5/3 filter") ("SEIChromaResamplingVerticalFilterType", m_chromaResamplingVerFilterIdc, 2, "Defines the Index of the chroma sampling vertical filter\n" "\t0: unspecified - Chroma filter is unknown or is determined by the application" "\t1: User-defined - Filter coefficients are specified in the chroma sampling filter hint SEI message" "\t2: Standards-defined - ITU-T Rec. T.800 | ISO/IEC15444-1, 5/3 filter") ("SEIFramePacking", m_framePackingSEIEnabled, false, "Control generation of frame packing SEI messages") ("SEIFramePackingType", m_framePackingSEIType, 0, "Define frame packing arrangement\n" "\t3: side by side - frames are displayed horizontally\n" "\t4: top bottom - frames are displayed vertically\n" "\t5: frame alternation - one frame is alternated with the other") ("SEIFramePackingId", m_framePackingSEIId, 0, "Id of frame packing SEI message for a given session") ("SEIFramePackingQuincunx", m_framePackingSEIQuincunx, 0, "Indicate the presence of a Quincunx type video frame") ("SEIFramePackingInterpretation", m_framePackingSEIInterpretation, 0, "Indicate the interpretation of the frame pair\n" "\t0: unspecified\n" "\t1: stereo pair, frame0 represents left view\n" "\t2: stereo pair, frame0 represents right view") ("SEISegmentedRectFramePacking", m_segmentedRectFramePackingSEIEnabled, false, "Controls generation of segmented rectangular frame packing SEI messages") ("SEISegmentedRectFramePackingCancel", m_segmentedRectFramePackingSEICancel, false, "If equal to 1, cancels the persistence of any previous SRFPA SEI message") ("SEISegmentedRectFramePackingType", m_segmentedRectFramePackingSEIType, 0, "Specifies the arrangement of the frames in the reconstructed picture") ("SEISegmentedRectFramePackingPersistence", m_segmentedRectFramePackingSEIPersistence, false, "If equal to 0, the SEI applies to the current frame only") ("SEIDisplayOrientation", m_displayOrientationSEIAngle, 0, "Control generation of display orientation SEI messages\n" "\tN: 0 < N < (2^16 - 1) enable display orientation SEI message with anticlockwise_rotation = N and display_orientation_repetition_period = 1\n" "\t0: disable") ("SEITemporalLevel0Index", m_temporalLevel0IndexSEIEnabled, false, "Control generation of temporal level 0 index SEI messages") ("SEIGradualDecodingRefreshInfo", m_gradualDecodingRefreshInfoEnabled, false, "Control generation of gradual decoding refresh information SEI message") ("SEINoDisplay", m_noDisplaySEITLayer, 0, "Control generation of no display SEI message\n" "\tN: 0 < N enable no display SEI message for temporal layer N or higher\n" "\t0: disable") ("SEIDecodingUnitInfo", m_decodingUnitInfoSEIEnabled, false, "Control generation of decoding unit information SEI message.") ("SEISOPDescription", m_SOPDescriptionSEIEnabled, false, "Control generation of SOP description SEI messages") ("SEIScalableNesting", m_scalableNestingSEIEnabled, false, "Control generation of scalable nesting SEI messages") ("SEITempMotionConstrainedTileSets", m_tmctsSEIEnabled, false, "Control generation of temporal motion constrained tile sets SEI message") #if MCTS_ENC_CHECK ("SEITMCTSTileConstraint", m_tmctsSEITileConstraint, false, "Constrain motion vectors at tile boundaries") #endif #if MCTS_EXTRACTION ("SEITMCTSExtractionInfo", m_tmctsExtractionSEIEnabled, false, "Control generation of MCTS extraction info SEI messages") #endif ("SEITimeCodeEnabled", m_timeCodeSEIEnabled, false, "Control generation of time code information SEI message") ("SEITimeCodeNumClockTs", m_timeCodeSEINumTs, 0, "Number of clock time sets [0..3]") ("SEITimeCodeTimeStampFlag", cfg_timeCodeSeiTimeStampFlag, cfg_timeCodeSeiTimeStampFlag, "Time stamp flag associated to each time set") ("SEITimeCodeFieldBasedFlag", cfg_timeCodeSeiNumUnitFieldBasedFlag, cfg_timeCodeSeiNumUnitFieldBasedFlag, "Field based flag associated to each time set") ("SEITimeCodeCountingType", cfg_timeCodeSeiCountingType, cfg_timeCodeSeiCountingType, "Counting type associated to each time set") ("SEITimeCodeFullTsFlag", cfg_timeCodeSeiFullTimeStampFlag, cfg_timeCodeSeiFullTimeStampFlag, "Full time stamp flag associated to each time set") ("SEITimeCodeDiscontinuityFlag", cfg_timeCodeSeiDiscontinuityFlag, cfg_timeCodeSeiDiscontinuityFlag, "Discontinuity flag associated to each time set") ("SEITimeCodeCntDroppedFlag", cfg_timeCodeSeiCntDroppedFlag, cfg_timeCodeSeiCntDroppedFlag, "Counter dropped flag associated to each time set") ("SEITimeCodeNumFrames", cfg_timeCodeSeiNumberOfFrames, cfg_timeCodeSeiNumberOfFrames, "Number of frames associated to each time set") ("SEITimeCodeSecondsValue", cfg_timeCodeSeiSecondsValue, cfg_timeCodeSeiSecondsValue, "Seconds value for each time set") ("SEITimeCodeMinutesValue", cfg_timeCodeSeiMinutesValue, cfg_timeCodeSeiMinutesValue, "Minutes value for each time set") ("SEITimeCodeHoursValue", cfg_timeCodeSeiHoursValue, cfg_timeCodeSeiHoursValue, "Hours value for each time set") ("SEITimeCodeSecondsFlag", cfg_timeCodeSeiSecondsFlag, cfg_timeCodeSeiSecondsFlag, "Flag to signal seconds value presence in each time set") ("SEITimeCodeMinutesFlag", cfg_timeCodeSeiMinutesFlag, cfg_timeCodeSeiMinutesFlag, "Flag to signal minutes value presence in each time set") ("SEITimeCodeHoursFlag", cfg_timeCodeSeiHoursFlag, cfg_timeCodeSeiHoursFlag, "Flag to signal hours value presence in each time set") ("SEITimeCodeOffsetLength", cfg_timeCodeSeiTimeOffsetLength, cfg_timeCodeSeiTimeOffsetLength, "Time offset length associated to each time set") ("SEITimeCodeTimeOffset", cfg_timeCodeSeiTimeOffsetValue, cfg_timeCodeSeiTimeOffsetValue, "Time offset associated to each time set") ("SEIKneeFunctionInfo", m_kneeSEIEnabled, false, "Control generation of Knee function SEI messages") ("SEIKneeFunctionId", m_kneeFunctionInformationSEI.m_kneeFunctionId, 0, "Specifies Id of Knee function SEI message for a given session") ("SEIKneeFunctionCancelFlag", m_kneeFunctionInformationSEI.m_kneeFunctionCancelFlag, false, "Indicates that Knee function SEI message cancels the persistence or follows") ("SEIKneeFunctionPersistenceFlag", m_kneeFunctionInformationSEI.m_kneeFunctionPersistenceFlag, true, "Specifies the persistence of the Knee function SEI message") ("SEIKneeFunctionInputDrange", m_kneeFunctionInformationSEI.m_inputDRange, 1000, "Specifies the peak luminance level for the input picture of Knee function SEI messages") ("SEIKneeFunctionInputDispLuminance", m_kneeFunctionInformationSEI.m_inputDispLuminance, 100, "Specifies the expected display brightness for the input picture of Knee function SEI messages") ("SEIKneeFunctionOutputDrange", m_kneeFunctionInformationSEI.m_outputDRange, 4000, "Specifies the peak luminance level for the output picture of Knee function SEI messages") ("SEIKneeFunctionOutputDispLuminance", m_kneeFunctionInformationSEI.m_outputDispLuminance, 800, "Specifies the expected display brightness for the output picture of Knee function SEI messages") ("SEIKneeFunctionNumKneePointsMinus1", cfg_kneeSEINumKneePointsMinus1, 2, "Specifies the number of knee points - 1") ("SEIKneeFunctionInputKneePointValue", cfg_kneeSEIInputKneePointValue, cfg_kneeSEIInputKneePointValue, "Array of input knee point") ("SEIKneeFunctionOutputKneePointValue", cfg_kneeSEIOutputKneePointValue, cfg_kneeSEIOutputKneePointValue, "Array of output knee point") ("SEIMasteringDisplayColourVolume", m_masteringDisplay.colourVolumeSEIEnabled, false, "Control generation of mastering display colour volume SEI messages") ("SEIMasteringDisplayMaxLuminance", m_masteringDisplay.maxLuminance, 10000u, "Specifies the mastering display maximum luminance value in units of 1/10000 candela per square metre (32-bit code value)") ("SEIMasteringDisplayMinLuminance", m_masteringDisplay.minLuminance, 0u, "Specifies the mastering display minimum luminance value in units of 1/10000 candela per square metre (32-bit code value)") ("SEIMasteringDisplayPrimaries", cfg_DisplayPrimariesCode, cfg_DisplayPrimariesCode, "Mastering display primaries for all three colour planes in CIE xy coordinates in increments of 1/50000 (results in the ranges 0 to 50000 inclusive)") ("SEIMasteringDisplayWhitePoint", cfg_DisplayWhitePointCode, cfg_DisplayWhitePointCode, "Mastering display white point CIE xy coordinates in normalised increments of 1/50000 (e.g. 0.333 = 16667)") ("SEIPreferredTransferCharacteristics", m_preferredTransferCharacteristics, -1, "Value for the preferred_transfer_characteristics field of the Alternative transfer characteristics SEI which will override the corresponding entry in the VUI. If negative, do not produce the respective SEI message") ("SEIGreenMetadataType", m_greenMetadataType, 0u, "Value for the green_metadata_type specifies the type of metadata that is present in the SEI message. If green_metadata_type is 1, then metadata enabling quality recovery after low-power encoding is present") ("SEIXSDMetricType", m_xsdMetricType, 0u, "Value for the xsd_metric_type indicates the type of the objective quality metric. PSNR is the only type currently supported") ("SEICCVEnabled", m_ccvSEIEnabled, false, "Enables the Content Colour Volume SEI message") ("SEICCVCancelFlag", m_ccvSEICancelFlag, true, "Specifies the persistence of any previous content colour volume SEI message in output order.") ("SEICCVPersistenceFlag", m_ccvSEIPersistenceFlag, false, "Specifies the persistence of the content colour volume SEI message for the current layer.") ("SEICCVPrimariesPresent", m_ccvSEIPrimariesPresentFlag, true, "Specifies whether the CCV primaries are present in the content colour volume SEI message.") ("m_ccvSEIPrimariesX0", m_ccvSEIPrimariesX[0], 0.300, "Specifies the x coordinate of the first (green) primary for the content colour volume SEI message") ("m_ccvSEIPrimariesY0", m_ccvSEIPrimariesY[0], 0.600, "Specifies the y coordinate of the first (green) primary for the content colour volume SEI message") ("m_ccvSEIPrimariesX1", m_ccvSEIPrimariesX[1], 0.150, "Specifies the x coordinate of the second (blue) primary for the content colour volume SEI message") ("m_ccvSEIPrimariesY1", m_ccvSEIPrimariesY[1], 0.060, "Specifies the y coordinate of the second (blue) primary for the content colour volume SEI message") ("m_ccvSEIPrimariesX2", m_ccvSEIPrimariesX[2], 0.640, "Specifies the x coordinate of the third (red) primary for the content colour volume SEI message") ("m_ccvSEIPrimariesY2", m_ccvSEIPrimariesY[2], 0.330, "Specifies the y coordinate of the third (red) primary for the content colour volume SEI message") ("SEICCVMinLuminanceValuePresent", m_ccvSEIMinLuminanceValuePresentFlag, true, "Specifies whether the CCV min luminance value is present in the content colour volume SEI message") ("SEICCVMinLuminanceValue", m_ccvSEIMinLuminanceValue, 0.0, "specifies the CCV min luminance value in the content colour volume SEI message") ("SEICCVMaxLuminanceValuePresent", m_ccvSEIMaxLuminanceValuePresentFlag, true, "Specifies whether the CCV max luminance value is present in the content colour volume SEI message") ("SEICCVMaxLuminanceValue", m_ccvSEIMaxLuminanceValue, 0.1, "specifies the CCV max luminance value in the content colour volume SEI message") ("SEICCVAvgLuminanceValuePresent", m_ccvSEIAvgLuminanceValuePresentFlag, true, "Specifies whether the CCV avg luminance value is present in the content colour volume SEI message") ("SEICCVAvgLuminanceValue", m_ccvSEIAvgLuminanceValue, 0.01, "specifies the CCV avg luminance value in the content colour volume SEI message") #if SHUTTER_INTERVAL_SEI_MESSAGE ("SEIShutterIntervalEnabled", m_siiSEIEnabled, false, "Controls if shutter interval information SEI message is enabled") ("SEISiiTimeScale", m_siiSEITimeScale, 27000000u, "Specifies sii_time_scale") ("SEISiiInputNumUnitsInShutterInterval", cfg_siiSEIInputNumUnitsInSI, cfg_siiSEIInputNumUnitsInSI, "Specifies sub_layer_num_units_in_shutter_interval") #endif #if SEI_ENCODER_CONTROL // film grain characteristics SEI ("SEIFGCEnabled", m_fgcSEIEnabled, false, "Control generation of the film grain characteristics SEI message") ("SEIFGCCancelFlag", m_fgcSEICancelFlag, false, "Specifies the persistence of any previous film grain characteristics SEI message in output order.") ("SEIFGCPersistenceFlag", m_fgcSEIPersistenceFlag, false, "Specifies the persistence of the film grain characteristics SEI message for the current layer.") ("SEIFGCModelID", m_fgcSEIModelID, 0u, "Specifies the film grain simulation model. 0: frequency filtering; 1: auto-regression.") ("SEIFGCSepColourDescPresentFlag", m_fgcSEISepColourDescPresentFlag, false, "Specifies the presense of a distinct colour space description for the film grain charactersitics specified in the SEI message.") ("SEIFGCBlendingModeID", m_fgcSEIBlendingModeID, 0u, "Specifies the blending mode used to blend the simulated film grain with the decoded images. 0: additive; 1: multiplicative.") ("SEIFGCLog2ScaleFactor", m_fgcSEILog2ScaleFactor, 2u, "Specifies a scale factor used in the film grain characterization equations.") ("SEIFGCCompModelPresentComp0", m_fgcSEICompModelPresent[0], false, "Specifies the presense of film grain modelling on colour component 0.") ("SEIFGCCompModelPresentComp1", m_fgcSEICompModelPresent[1], false, "Specifies the presense of film grain modelling on colour component 1.") ("SEIFGCCompModelPresentComp2", m_fgcSEICompModelPresent[2], false, "Specifies the presense of film grain modelling on colour component 2.") #if JVET_X0048_X0103_FILM_GRAIN ("SEIFGCAnalysisEnabled", m_fgcSEIAnalysisEnabled, false, "Control adaptive film grain parameter estimation - film grain analysis") ("SEIFGCExternalMask", m_fgcSEIExternalMask, string( "" ), "Read external file with mask for film grain analysis. If empty string, use internally calculated mask.") ("SEIFGCExternalDenoised", m_fgcSEIExternalDenoised, string( "" ), "Read external file with denoised sequence for film grain analysis. If empty string, use MCTF for denoising.") ("SEIFGCPerPictureSEI", m_fgcSEIPerPictureSEI, false, "Film Grain SEI is added for each picture as speciffied in RDD5 to ensure bit accurate synthesis in tricky mode") ("SEIFGCNumIntensityIntervalMinus1Comp0", m_fgcSEINumIntensityIntervalMinus1[0], 0u, "Specifies the number of intensity intervals minus1 on colour component 0.") ("SEIFGCNumIntensityIntervalMinus1Comp1", m_fgcSEINumIntensityIntervalMinus1[1], 0u, "Specifies the number of intensity intervals minus1 on colour component 1.") ("SEIFGCNumIntensityIntervalMinus1Comp2", m_fgcSEINumIntensityIntervalMinus1[2], 0u, "Specifies the number of intensity intervals minus1 on colour component 2.") ("SEIFGCNumModelValuesMinus1Comp0", m_fgcSEINumModelValuesMinus1[0], 0u, "Specifies the number of component model values minus1 on colour component 0.") ("SEIFGCNumModelValuesMinus1Comp1", m_fgcSEINumModelValuesMinus1[1], 0u, "Specifies the number of component model values minus1 on colour component 1.") ("SEIFGCNumModelValuesMinus1Comp2", m_fgcSEINumModelValuesMinus1[2], 0u, "Specifies the number of component model values minus1 on colour component 2.") ("SEIFGCIntensityIntervalLowerBoundComp0", cfg_FgcSEIIntensityIntervalLowerBoundComp[0], cfg_FgcSEIIntensityIntervalLowerBoundComp[0], "Specifies the lower bound for the intensity intervals on colour component 0.") ("SEIFGCIntensityIntervalLowerBoundComp1", cfg_FgcSEIIntensityIntervalLowerBoundComp[1], cfg_FgcSEIIntensityIntervalLowerBoundComp[1], "Specifies the lower bound for the intensity intervals on colour component 1.") ("SEIFGCIntensityIntervalLowerBoundComp2", cfg_FgcSEIIntensityIntervalLowerBoundComp[2], cfg_FgcSEIIntensityIntervalLowerBoundComp[2], "Specifies the lower bound for the intensity intervals on colour component 2.") ("SEIFGCIntensityIntervalUpperBoundComp0", cfg_FgcSEIIntensityIntervalUpperBoundComp[0], cfg_FgcSEIIntensityIntervalUpperBoundComp[0], "Specifies the upper bound for the intensity intervals on colour component 0.") ("SEIFGCIntensityIntervalUpperBoundComp1", cfg_FgcSEIIntensityIntervalUpperBoundComp[1], cfg_FgcSEIIntensityIntervalUpperBoundComp[1], "Specifies the upper bound for the intensity intervals on colour component 1.") ("SEIFGCIntensityIntervalUpperBoundComp2", cfg_FgcSEIIntensityIntervalUpperBoundComp[2], cfg_FgcSEIIntensityIntervalUpperBoundComp[2], "Specifies the upper bound for the intensity intervals on colour component 2.") ("SEIFGCCompModelValuesComp0", cfg_FgcSEICompModelValueComp[0], cfg_FgcSEICompModelValueComp[0], "Specifies the component model values on colour component 0.") ("SEIFGCCompModelValuesComp1", cfg_FgcSEICompModelValueComp[1], cfg_FgcSEICompModelValueComp[1], "Specifies the component model values on colour component 1.") ("SEIFGCCompModelValuesComp2", cfg_FgcSEICompModelValueComp[2], cfg_FgcSEICompModelValueComp[2], "Specifies the component model values on colour component 2.") #endif // content light level SEI ("SEICLLEnabled", m_cllSEIEnabled, false, "Control generation of the content light level SEI message") ("SEICLLMaxContentLightLevel", m_cllSEIMaxContentLevel, 0u, "When not equal to 0, specifies an upper bound on the maximum light level among all individual samples in a 4:4:4 representation " "of red, green, and blue colour primary intensities in the linear light domain for the pictures of the CLVS, " "in units of candelas per square metre.When equal to 0, no such upper bound is indicated.") ("SEICLLMaxPicAvgLightLevel", m_cllSEIMaxPicAvgLevel, 0u, "When not equal to 0, specifies an upper bound on the maximum average light level among the samples in a 4:4:4 representation " "of red, green, and blue colour primary intensities in the linear light domain for any individual picture of the CLVS, " "in units of candelas per square metre.When equal to 0, no such upper bound is indicated.") // ambient viewing environment SEI ("SEIAVEEnabled", m_aveSEIEnabled, false, "Control generation of the ambient viewing environment SEI message") ("SEIAVEAmbientIlluminance", m_aveSEIAmbientIlluminance, 100000u, "Specifies the environmental illluminance of the ambient viewing environment in units of 1/10000 lux for the ambient viewing enviornment SEI message") ("SEIAVEAmbientLightX", m_aveSEIAmbientLightX, 15635u, "Specifies the normalized x chromaticity coordinate of the environmental ambient light in the nominal viewing enviornment according to the CIE 1931 defination in units of 1/50000 lux for the ambient viewing enviornment SEI message") ("SEIAVEAmbientLightY", m_aveSEIAmbientLightY, 16450u, "Specifies the normalized y chromaticity coordinate of the environmental ambient light in the nominal viewing enviornment according to the CIE 1931 defination in units of 1/50000 lux for the ambient viewing enviornment SEI message") #endif ("SEIErpEnabled", m_erpSEIEnabled, false, "Control generation of equirectangular projection SEI messages") ("SEIErpCancelFlag", m_erpSEICancelFlag, true, "Indicate that equirectangular projection SEI message cancels the persistence or follows") ("SEIErpPersistenceFlag", m_erpSEIPersistenceFlag, false, "Specifies the persistence of the equirectangular projection SEI messages") ("SEIErpGuardBandFlag", m_erpSEIGuardBandFlag, false, "Indicate the existence of guard band areas in the constituent picture") ("SEIErpGuardBandType", m_erpSEIGuardBandType, 0u, "Indicate the type of the guard band") ("SEIErpLeftGuardBandWidth", m_erpSEILeftGuardBandWidth, 0u, "Indicate the width of the guard band on the left side of the constituent picture") ("SEIErpRightGuardBandWidth", m_erpSEIRightGuardBandWidth, 0u, "Indicate the width of the guard band on the right side of the constituent picture") ("SEISphereRotationEnabled", m_sphereRotationSEIEnabled, false, "Control generation of sphere rotation SEI messages") ("SEISphereRotationCancelFlag", m_sphereRotationSEICancelFlag, true, "Indicate that sphere rotation SEI message cancels the persistence or follows") ("SEISphereRotationPersistenceFlag", m_sphereRotationSEIPersistenceFlag, false, "Specifies the persistence of the sphere rotation SEI messages") ("SEISphereRotationYaw", m_sphereRotationSEIYaw, 0, "Specifies the value of the yaw rotation angle") ("SEISphereRotationPitch", m_sphereRotationSEIPitch, 0, "Specifies the value of the pitch rotation angle") ("SEISphereRotationRoll", m_sphereRotationSEIRoll, 0, "Specifies the value of the roll rotation angle") ("SEIOmniViewportEnabled", m_omniViewportSEIEnabled, false, "Control generation of omni viewport SEI messages") ("SEIOmniViewportId", m_omniViewportSEIId, 0u, "An identifying number that may be used to identify the purpose of the one or more recommended viewport regions") ("SEIOmniViewportCancelFlag", m_omniViewportSEICancelFlag, true, "Indicate that omni viewport SEI message cancels the persistence or follows") ("SEIOmniViewportPersistenceFlag", m_omniViewportSEIPersistenceFlag, false, "Specifies the persistence of the omni viewport SEI messages") ("SEIOmniViewportCntMinus1", m_omniViewportSEICntMinus1, 0u, "specifies the number of recommended viewport regions minus 1") ("SEIOmniViewportAzimuthCentre", cfg_omniViewportSEIAzimuthCentre, cfg_omniViewportSEIAzimuthCentre, "Indicate the centre of the i-th recommended viewport region") ("SEIOmniViewportElevationCentre", cfg_omniViewportSEIElevationCentre, cfg_omniViewportSEIElevationCentre, "Indicate the centre of the i-th recommended viewport region") ("SEIOmniViewportTiltCentre", cfg_omniViewportSEITiltCentre, cfg_omniViewportSEITiltCentre, "Indicates the tilt angle of the i-th recommended viewport region") ("SEIOmniViewportHorRange", cfg_omniViewportSEIHorRange, cfg_omniViewportSEIHorRange, "Indicates the azimuth range of the i-th recommended viewport region") ("SEIOmniViewportVerRange", cfg_omniViewportSEIVerRange, cfg_omniViewportSEIVerRange, "Indicates the elevation range of the i-th recommended viewport region") ("SEICmpEnabled", m_cmpSEIEnabled, false, "Controls generation of cubemap projection SEI message") ("SEICmpCancelFlag", m_cmpSEICmpCancelFlag, true, "Specifies the persistence of any previous cubemap projection SEI message in output order.") ("SEICmpPersistenceFlag", m_cmpSEICmpPersistenceFlag, false, "Specifies the persistence of the cubemap projection SEI message for the current layer.") ("SEIRwpEnabled", m_rwpSEIEnabled, false, "Controls if region-wise packing SEI message enabled") ("SEIRwpCancelFlag", m_rwpSEIRwpCancelFlag, true, "Specifies the persistence of any previous region-wise packing SEI message in output order.") ("SEIRwpPersistenceFlag", m_rwpSEIRwpPersistenceFlag, false, "Specifies the persistence of the region-wise packing SEI message for the current layer.") ("SEIRwpConstituentPictureMatchingFlag", m_rwpSEIConstituentPictureMatchingFlag, false, "Specifies the information in the SEI message apply individually to each constituent picture or to the projected picture.") ("SEIRwpNumPackedRegions", m_rwpSEINumPackedRegions, 0, "specifies the number of packed regions when constituent picture matching flag is equal to 0.") ("SEIRwpProjPictureWidth", m_rwpSEIProjPictureWidth, 0, "Specifies the width of the projected picture.") ("SEIRwpProjPictureHeight", m_rwpSEIProjPictureHeight, 0, "Specifies the height of the projected picture.") ("SEIRwpPackedPictureWidth", m_rwpSEIPackedPictureWidth, 0, "specifies the width of the packed picture.") ("SEIRwpPackedPictureHeight", m_rwpSEIPackedPictureHeight, 0, "Specifies the height of the packed picture.") ("SEIRwpTransformType", cfg_rwpSEIRwpTransformType, cfg_rwpSEIRwpTransformType, "specifies the rotation and mirroring to be applied to the i-th packed region.") ("SEIRwpGuardBandFlag", cfg_rwpSEIRwpGuardBandFlag, cfg_rwpSEIRwpGuardBandFlag, "specifies the existence of guard band in the i-th packed region.") ("SEIRwpProjRegionWidth", cfg_rwpSEIProjRegionWidth, cfg_rwpSEIProjRegionWidth, "specifies the width of the i-th projected region.") ("SEIRwpProjRegionHeight", cfg_rwpSEIProjRegionHeight, cfg_rwpSEIProjRegionHeight, "specifies the height of the i-th projected region.") ("SEIRwpProjRegionTop", cfg_rwpSEIRwpSEIProjRegionTop, cfg_rwpSEIRwpSEIProjRegionTop, "specifies the top sample row of the i-th projected region.") ("SEIRwpProjRegionLeft", cfg_rwpSEIProjRegionLeft, cfg_rwpSEIProjRegionLeft, "specifies the left-most sample column of the i-th projected region.") ("SEIRwpPackedRegionWidth", cfg_rwpSEIPackedRegionWidth, cfg_rwpSEIPackedRegionWidth, "specifies the width of the i-th packed region.") ("SEIRwpPackedRegionHeight", cfg_rwpSEIPackedRegionHeight, cfg_rwpSEIPackedRegionHeight, "specifies the height of the i-th packed region.") ("SEIRwpPackedRegionTop", cfg_rwpSEIPackedRegionTop, cfg_rwpSEIPackedRegionTop, "specifies the top luma sample row of the i-th packed region.") ("SEIRwpPackedRegionLeft", cfg_rwpSEIPackedRegionLeft, cfg_rwpSEIPackedRegionLeft, "specifies the left-most luma sample column of the i-th packed region.") ("SEIRwpLeftGuardBandWidth", cfg_rwpSEIRwpLeftGuardBandWidth, cfg_rwpSEIRwpLeftGuardBandWidth, "specifies the width of the guard band on the left side of the i-th packed region.") ("SEIRwpRightGuardBandWidth", cfg_rwpSEIRwpRightGuardBandWidth, cfg_rwpSEIRwpRightGuardBandWidth, "specifies the width of the guard band on the right side of the i-th packed region.") ("SEIRwpTopGuardBandHeight", cfg_rwpSEIRwpTopGuardBandHeight, cfg_rwpSEIRwpTopGuardBandHeight, "specifies the height of the guard band above the i-th packed region.") ("SEIRwpBottomGuardBandHeight", cfg_rwpSEIRwpBottomGuardBandHeight, cfg_rwpSEIRwpBottomGuardBandHeight, "specifies the height of the guard band below the i-th packed region.") ("SEIRwpGuardBandNotUsedForPredFlag", cfg_rwpSEIRwpGuardBandNotUsedForPredFlag, cfg_rwpSEIRwpGuardBandNotUsedForPredFlag, "Specifies if the guard bands is used in the inter prediction process.") ("SEIRwpGuardBandType", cfg_rwpSEIRwpGuardBandType, cfg_rwpSEIRwpGuardBandType, "Specifies the type of the guard bands for the i-th packed region.") ("SEIFviEnabled", m_fisheyeVIdeoInfoSEIEnabled, false, "Controls if fisheye video information SEI message enabled") ("SEIFviCancelFlag", m_fisheyeVideoInfoSEI.m_fisheyeCancelFlag, true, "Specifies the persistence of any previous fisheye video information SEI message in output order.") ("SEIFviPersistenceFlag", m_fisheyeVideoInfoSEI.m_fisheyePersistenceFlag, false, "Specifies the persistence of the fisheye video information SEI message for the current layer.") ("SEIFviViewDimensionIdc", m_fisheyeVideoInfoSEI.m_fisheyeViewDimensionIdc, 0u, "Specifies the alignment and viewing direction of a fisheye lens") ("SEIFviNumActiveAreasMinus1", cfg_fviSEIFisheyeNumActiveAreasMinus1, 0u, "Specifies the number of active areas in the coded picture minus 1") ("SEIFviCircularRegionCentreX", cfg_fviSEIFisheyeCircularRegionCentreX, cfg_fviSEIFisheyeCircularRegionCentreX, "Specifies the horizontal coordinates of the centre of the circular region that contains the i-th active area in the coded picture") ("SEIFviCircularRegionCentreY", cfg_fviSEIFisheyeCircularRegionCentreY, cfg_fviSEIFisheyeCircularRegionCentreY, "Specifies the vertical coordinates of the centre of the circular region that contains the i-th active area in the coded picture") ("SEIFviRectRegionTop", cfg_fviSEIFisheyeRectRegionTop, cfg_fviSEIFisheyeRectRegionTop, "Specifies the vertical coordinates of the top-left corner of the i-th rectangular region that contains the i-th active area") ("SEIFviRectRegionLeft", cfg_fviSEIFisheyeRectRegionLeft, cfg_fviSEIFisheyeRectRegionLeft, "Specifies the horizontal coordinates of the top-left corner of the i-th rectangular region that contains the i-th active area") ("SEIFviRectRegionWidth", cfg_fviSEIFisheyeRectRegionWidth, cfg_fviSEIFisheyeRectRegionWidth, "Specifies the width of the i-th rectangular region that contains the i-th active area") ("SEIFviRectRegionHeight", cfg_fviSEIFisheyeRectRegionHeight, cfg_fviSEIFisheyeRectRegionHeight, "Specifies the height of the i-th rectangular region that contains the i-th active area") ("SEIFviCircularRegionRadius", cfg_fviSEIFisheyeCircularRegionRadius, cfg_fviSEIFisheyeCircularRegionRadius, "Specifies the radius of the circular region that contains the i-th active area that is defined as a length from the centre of the circular region to the outermost pixel boundary of the circular region, that corresponds to the maximum field of view of the i-th fisheye lens") ("SEIFviSceneRadius", cfg_fviSEIFisheyeSceneRadius, cfg_fviSEIFisheyeSceneRadius, "Specifies the radius of a circular region within the i-th active area where the obstruction is not included in the region") ("SEIFviCameraCentreAzimuth", cfg_fviSEIFisheyeCameraCentreAzimuth, cfg_fviSEIFisheyeCameraCentreAzimuth, "Indicates the spherical coordinates that correspond to the centre of the circular region that contains the i-th active area") ("SEIFviCameraCentreElevation", cfg_fviSEIFisheyeCameraCentreElevation, cfg_fviSEIFisheyeCameraCentreElevation, "Indicates the spherical coordinates that correspond to the centre of the circular region that contains the i-th active area") ("SEIFviCameraCentreTilt", cfg_fviSEIFisheyeCameraCentreTilt, cfg_fviSEIFisheyeCameraCentreTilt, "Indicates the spherical coordinates that correspond to the centre of the circular region that contains the i-th active area") ("SEIFviCameraCentreOffsetX", cfg_fviSEIFisheyeCameraCentreOffsetX, cfg_fviSEIFisheyeCameraCentreOffsetX, "Indicates the XYZ offset values of the focal centre of the fisheye camera lens corresponding to the i-th active area from the focal centre origin of the overall fisheye camera configuration.") ("SEIFviCameraCentreOffsetY", cfg_fviSEIFisheyeCameraCentreOffsetY, cfg_fviSEIFisheyeCameraCentreOffsetY, "Indicates the XYZ offset values of the focal centre of the fisheye camera lens corresponding to the i-th active area from the focal centre origin of the overall fisheye camera configuration.") ("SEIFviCameraCenterOffsetZ", cfg_fviSEIFisheyeCameraCentreOffsetZ, cfg_fviSEIFisheyeCameraCentreOffsetZ, "Indicates the XYZ offset values of the focal centre of the fisheye camera lens corresponding to the i-th active area from the focal centre origin of the overall fisheye camera configuration.") ("SEIFviFieldOfView", cfg_fviSEIFisheyeFieldOfView, cfg_fviSEIFisheyeFieldOfView, "Specifies the field of view of the lens that corresponds to the i-th active area") ("SEIFviNumPolynomialCoeffs", cfg_fviSEIFisheyeNumPolynomialCoeffs, cfg_fviSEIFisheyeNumPolynomialCoeffs, "Specifies the number of polynomial coefficients for the circular region") ("SEIFviPolynomialCoeff", cfg_fviSEIFisheyePolynomialCoeff, cfg_fviSEIFisheyePolynomialCoeff, "Specifies the j-th polynomial coefficient value of the curve function that maps the normalized distance of a luma sample from the centre of the circular region corresponding to the i-th active area to the angular value of a sphere coordinate from the normal vector of a nominal imaging plane that passes through the centre of the sphere coordinate system for the i-th active region.") ("SEIRegionalNestingFileRoot,-rns", m_regionalNestingSEIFileRoot, string(""), "Regional nesting SEI parameters root file name (wo num ext); only the file name base is to be added. Underscore and POC would be automatically addded to . E.g. \"-rns rns\" will search for files rns_0.txt, rns_1.txt, ...") ("SEIAnnotatedRegionsFileRoot,-ar", m_arSEIFileRoot, string(""), "Annotated region SEI parameters root file name (wo num ext); only the file name base is to be added. Underscore and POC would be automatically addded to . E.g. \"-ar ar\" will search for files ar_0.txt, ar_1.txt, ...") #if JCTVC_AD0021_SEI_MANIFEST ("SEISEIManifestEnabled", m_SEIManifestSEIEnabled, false, "Controls if SEI Manifest SEI messages enabled") #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION ("SEISEIPrefixIndicationEnabled", m_SEIPrefixIndicationSEIEnabled, false, "Controls if SEI Prefix Indications SEI messages enabled") #endif ; opts.addOptions() ("TemporalFilter", m_gopBasedTemporalFilterEnabled, false, "Enable GOP based temporal filter. Disabled per default") ("TemporalFilterPastRefs", m_gopBasedTemporalFilterPastRefs, TF_DEFAULT_REFS, "Number of past references for temporal prefilter") ("TemporalFilterFutureRefs", m_gopBasedTemporalFilterFutureRefs, TF_DEFAULT_REFS, "Number of future references for temporal prefilter") ("FirstValidFrame", m_firstValidFrame, 0, "First valid frame") ("LastValidFrame", m_lastValidFrame, MAX_INT, "Last valid frame") ("TemporalFilterStrengthFrame*", m_gopBasedTemporalFilterStrengths, std::map(), "Strength for every * frame in GOP based temporal filter, where * is an integer." " E.g. --TemporalFilterStrengthFrame8 0.95 will enable GOP based temporal filter at every 8th frame with strength 0.95"); #if EXTENSION_360_VIDEO TExt360AppEncCfg::TExt360AppEncCfgContext ext360CfgContext; m_ext360.addOptions(opts, ext360CfgContext); #endif for(Int i=1; i& argv_unhandled = po::scanArgv(opts, argc, (const TChar**) argv, err); for (list::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { fprintf(stderr, "Unhandled argument ignored: `%s'\n", *it); } if (argc == 1 || do_help) { /* argc == 1: no options have been specified */ po::doHelp(cout, opts); return false; } if (err.is_errored) { if (!warnUnknowParameter) { /* error report has already been printed on stderr */ return false; } } /* * Set any derived parameters */ m_inputFileWidth = m_sourceWidth; m_inputFileHeight = m_sourceHeight; if (!inputPathPrefix.empty() && inputPathPrefix.back() != '/' && inputPathPrefix.back() != '\\' ) { inputPathPrefix += "/"; } m_inputFileName = inputPathPrefix + m_inputFileName; if (m_firstValidFrame < 0) { m_firstValidFrame = m_FrameSkip; } if (m_lastValidFrame < 0) { m_lastValidFrame = m_firstValidFrame + m_framesToBeEncoded - 1; } m_framesToBeEncoded = ( m_framesToBeEncoded + m_temporalSubsampleRatio - 1 ) / m_temporalSubsampleRatio; m_adIntraLambdaModifier = cfg_adIntraLambdaModifier.values; if(m_isField) { //Frame height m_sourceHeightOrg = m_sourceHeight; //Field height m_sourceHeight = m_sourceHeight >> 1; //number of fields to encode m_framesToBeEncoded *= 2; } if( !m_tileUniformSpacingFlag && m_numTileColumnsMinus1 > 0 ) { if (cfg_ColumnWidth.values.size() > m_numTileColumnsMinus1) { printf( "The number of columns whose width are defined is larger than the allowed number of columns.\n" ); exit( EXIT_FAILURE ); } else if (cfg_ColumnWidth.values.size() < m_numTileColumnsMinus1) { printf( "The width of some columns is not defined.\n" ); exit( EXIT_FAILURE ); } else { m_tileColumnWidth.resize(m_numTileColumnsMinus1); for(UInt i=0; i 0 ) { if (cfg_RowHeight.values.size() > m_numTileRowsMinus1) { printf( "The number of rows whose height are defined is larger than the allowed number of rows.\n" ); exit( EXIT_FAILURE ); } else if (cfg_RowHeight.values.size() < m_numTileRowsMinus1) { printf( "The height of some rows is not defined.\n" ); exit( EXIT_FAILURE ); } else { m_tileRowHeight.resize(m_numTileRowsMinus1); for(UInt i=0; i=0 && tmpWeightedPredictionMethod<=WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION); if (!(tmpWeightedPredictionMethod>=0 && tmpWeightedPredictionMethod<=WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION)) { exit(EXIT_FAILURE); } m_weightedPredictionMethod = WeightedPredictionMethod(tmpWeightedPredictionMethod); assert(tmpFastInterSearchMode>=0 && tmpFastInterSearchMode<=FASTINTERSEARCH_MODE3); if (tmpFastInterSearchMode<0 || tmpFastInterSearchMode>FASTINTERSEARCH_MODE3) { exit(EXIT_FAILURE); } m_fastInterSearchMode = FastInterSearchMode(tmpFastInterSearchMode); assert(tmpMotionEstimationSearchMethod>=0 && tmpMotionEstimationSearchMethod=MESEARCH_NUMBER_OF_METHODS) { exit(EXIT_FAILURE); } m_motionEstimationSearchMethod=MESearchMethod(tmpMotionEstimationSearchMethod); switch (UIProfile) { case UI_NONE: m_profile = Profile::NONE; m_onePictureOnlyConstraintFlag = false; break; case UI_MAIN: m_profile = Profile::MAIN; m_onePictureOnlyConstraintFlag = false; break; case UI_MAIN10: m_profile = Profile::MAIN10; m_onePictureOnlyConstraintFlag = false; break; case UI_MAINSTILLPICTURE: m_profile = Profile::MAINSTILLPICTURE; m_onePictureOnlyConstraintFlag = false; break; case UI_MAIN10_STILL_PICTURE: m_profile = Profile::MAIN10; m_onePictureOnlyConstraintFlag = true; break; case UI_MAINREXT: m_profile = Profile::MAINREXT; m_onePictureOnlyConstraintFlag = false; break; case UI_HIGHTHROUGHPUTREXT: m_profile = Profile::HIGHTHROUGHPUTREXT; m_onePictureOnlyConstraintFlag = false; break; default: if (UIProfile >= 1000 && UIProfile <= 12316) { m_profile = Profile::MAINREXT; if (m_bitDepthConstraint != 0 || tmpConstraintChromaFormat != 0) { fprintf(stderr, "Error: The bit depth and chroma format constraints are not used when an explicit RExt profile is specified\n"); exit(EXIT_FAILURE); } m_bitDepthConstraint = (UIProfile%100); m_intraConstraintFlag = ((UIProfile%10000)>=2000); m_onePictureOnlyConstraintFlag = (UIProfile >= 10000); switch ((UIProfile/100)%10) { case 0: tmpConstraintChromaFormat=400; break; case 1: tmpConstraintChromaFormat=420; break; case 2: tmpConstraintChromaFormat=422; break; default: tmpConstraintChromaFormat=444; break; } } else if (UIProfile >= 21308 && UIProfile <= 22316) { m_profile = Profile::HIGHTHROUGHPUTREXT; if (m_bitDepthConstraint != 0 || tmpConstraintChromaFormat != 0) { fprintf(stderr, "Error: The bit depth and chroma format constraints are not used when an explicit RExt profile is specified\n"); exit(EXIT_FAILURE); } m_bitDepthConstraint = (UIProfile%100); m_intraConstraintFlag = ((UIProfile%10000)>=2000); m_onePictureOnlyConstraintFlag = 0; if((UIProfile == UI_HIGHTHROUGHPUT_444) || (UIProfile == UI_HIGHTHROUGHPUT_444_10) ) { assert(m_cabacBypassAlignmentEnabledFlag==0); } switch ((UIProfile/100)%10) { case 0: tmpConstraintChromaFormat=400; break; case 1: tmpConstraintChromaFormat=420; break; case 2: tmpConstraintChromaFormat=422; break; default: tmpConstraintChromaFormat=444; break; } } else { fprintf(stderr, "Error: Unprocessed UI profile\n"); assert(0); exit(EXIT_FAILURE); } break; } switch (m_profile) { case Profile::HIGHTHROUGHPUTREXT: { if (m_bitDepthConstraint == 0) { m_bitDepthConstraint = 16; } m_chromaFormatConstraint = (tmpConstraintChromaFormat == 0) ? CHROMA_444 : numberToChromaFormat(tmpConstraintChromaFormat); } break; case Profile::MAINREXT: { if (m_bitDepthConstraint == 0 && tmpConstraintChromaFormat == 0) { // produce a valid combination, if possible. const Bool bUsingGeneralRExtTools = m_transformSkipRotationEnabledFlag || m_transformSkipContextEnabledFlag || m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT] || m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT] || !m_enableIntraReferenceSmoothing || m_persistentRiceAdaptationEnabledFlag || m_log2MaxTransformSkipBlockSize!=2; const Bool bUsingChromaQPAdjustment= m_diffCuChromaQpOffsetDepth >= 0; const Bool bUsingExtendedPrecision = m_extendedPrecisionProcessingFlag; if (m_onePictureOnlyConstraintFlag) { m_chromaFormatConstraint = CHROMA_444; if (m_intraConstraintFlag != true) { fprintf(stderr, "Error: Intra constraint flag must be true when one_picture_only_constraint_flag is true\n"); exit(EXIT_FAILURE); } const Int maxBitDepth = m_chromaFormatIDC==CHROMA_400 ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]); m_bitDepthConstraint = maxBitDepth>8 ? 16:8; } else { m_chromaFormatConstraint = NUM_CHROMA_FORMAT; automaticallySelectRExtProfile(bUsingGeneralRExtTools, bUsingChromaQPAdjustment, bUsingExtendedPrecision, m_intraConstraintFlag, m_bitDepthConstraint, m_chromaFormatConstraint, m_chromaFormatIDC==CHROMA_400 ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]), m_chromaFormatIDC); } } else if (m_bitDepthConstraint == 0 || tmpConstraintChromaFormat == 0) { fprintf(stderr, "Error: The bit depth and chroma format constraints must either both be specified or both be configured automatically\n"); exit(EXIT_FAILURE); } else { m_chromaFormatConstraint = numberToChromaFormat(tmpConstraintChromaFormat); } } break; case Profile::MAIN: case Profile::MAIN10: case Profile::MAINSTILLPICTURE: m_chromaFormatConstraint = (tmpConstraintChromaFormat == 0) ? m_chromaFormatIDC : numberToChromaFormat(tmpConstraintChromaFormat); m_bitDepthConstraint = (m_profile == Profile::MAIN10?10:8); break; case Profile::NONE: m_chromaFormatConstraint = m_chromaFormatIDC; m_bitDepthConstraint = m_chromaFormatIDC==CHROMA_400 ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]); break; default: fprintf(stderr, "Unknown profile selected\n"); exit(EXIT_FAILURE); break; } m_inputColourSpaceConvert = stringToInputColourSpaceConvert(inputColourSpaceConvert, true); // Picture width and height must be multiples of 8 and minCuSize const Int minCuSize = m_uiMaxCUHeight >> (m_uiMaxCUDepth - 1); const Int minResolutionMultiple = std::max(8, minCuSize); switch (m_conformanceWindowMode) { case 0: { // no conformance or padding m_confWinLeft = m_confWinRight = m_confWinTop = m_confWinBottom = 0; m_sourcePadding[1] = m_sourcePadding[0] = 0; break; } case 1: { // automatic padding to minimum CU size if (m_sourceWidth % minResolutionMultiple) { m_sourcePadding[0] = m_confWinRight = ((m_sourceWidth / minResolutionMultiple) + 1) * minResolutionMultiple - m_sourceWidth; m_sourceWidth += m_confWinRight; } if (m_sourceHeight % minResolutionMultiple) { m_sourcePadding[1] = m_confWinBottom = ((m_sourceHeight / minResolutionMultiple) + 1) * minResolutionMultiple - m_sourceHeight; m_sourceHeight += m_confWinBottom; if ( m_isField ) { m_sourceHeightOrg += m_confWinBottom << 1; m_sourcePadding[1] = m_confWinBottom << 1; } } if (m_sourcePadding[0] % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0) { fprintf(stderr, "Error: picture width is not an integer multiple of the specified chroma subsampling\n"); exit(EXIT_FAILURE); } if (m_sourcePadding[1] % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0) { fprintf(stderr, "Error: picture height is not an integer multiple of the specified chroma subsampling\n"); exit(EXIT_FAILURE); } if (m_sourcePadding[0]) { fprintf(stderr, "Info: Conformance window automatically enabled. Adding %i lumal pel horizontally\n", m_sourcePadding[0]); } if (m_sourcePadding[1]) { fprintf(stderr, "Info: Conformance window automatically enabled. Adding %i lumal pel vertically\n", m_sourcePadding[1]); } break; } case 2: { //padding m_sourceWidth += m_sourcePadding[0]; m_sourceHeight += m_sourcePadding[1]; m_confWinRight = m_sourcePadding[0]; m_confWinBottom = m_sourcePadding[1]; break; } case 3: { // conformance if ((m_confWinLeft == 0) && (m_confWinRight == 0) && (m_confWinTop == 0) && (m_confWinBottom == 0)) { fprintf(stderr, "Warning: Conformance window enabled, but all conformance window parameters set to zero\n"); } if ((m_sourcePadding[1] != 0) || (m_sourcePadding[0]!=0)) { fprintf(stderr, "Warning: Conformance window enabled, padding parameters will be ignored\n"); } m_sourcePadding[1] = m_sourcePadding[0] = 0; break; } } if ((m_sourceWidth% minResolutionMultiple) || (m_sourceHeight % minResolutionMultiple)) { fprintf(stderr, "Picture width or height (after padding) is not a multiple of 8 or minCuSize, please use ConformanceWindowMode=1 for automatic adjustment or ConformanceWindowMode=2 to specify padding manually!\n"); exit(EXIT_FAILURE); } if (tmpSliceMode<0 || tmpSliceMode>=Int(NUMBER_OF_SLICE_CONSTRAINT_MODES)) { fprintf(stderr, "Error: bad slice mode\n"); exit(EXIT_FAILURE); } m_sliceMode = SliceConstraint(tmpSliceMode); if (tmpSliceSegmentMode<0 || tmpSliceSegmentMode>=Int(NUMBER_OF_SLICE_CONSTRAINT_MODES)) { fprintf(stderr, "Error: bad slice segment mode\n"); exit(EXIT_FAILURE); } m_sliceSegmentMode = SliceConstraint(tmpSliceSegmentMode); if (tmpDecodedPictureHashSEIMappedType<0 || tmpDecodedPictureHashSEIMappedType>=Int(NUMBER_OF_HASHTYPES)) { fprintf(stderr, "Error: bad checksum mode\n"); exit(EXIT_FAILURE); } // Need to map values to match those of the SEI message: if (tmpDecodedPictureHashSEIMappedType==0) { m_decodedPictureHashSEIType=HASHTYPE_NONE; } else { m_decodedPictureHashSEIType=HashType(tmpDecodedPictureHashSEIMappedType-1); } // allocate slice-based dQP values m_aidQP = new Int[ m_framesToBeEncoded + m_iGOPSize + 1 ]; ::memset( m_aidQP, 0, sizeof(Int)*( m_framesToBeEncoded + m_iGOPSize + 1 ) ); if (m_qpIncrementAtSourceFrame.bPresent) { UInt switchingPOC=0; if (m_qpIncrementAtSourceFrame.value > m_FrameSkip) { // if switch source frame (ssf) = 10, and frame skip (fs)=2 and temporal subsample ratio (tsr) =1, then // for this simulation switch at POC 8 (=10-2). // if ssf=10, fs=2, tsr=2, then for this simulation, switch at POC 4 (=(10-2)/2): POC0=Src2, POC1=Src4, POC2=Src6, POC3=Src8, POC4=Src10 switchingPOC = (m_qpIncrementAtSourceFrame.value - m_FrameSkip) / m_temporalSubsampleRatio; } for(UInt i=switchingPOC; i<( m_framesToBeEncoded + m_iGOPSize + 1 ); i++) { m_aidQP[i]=1; } } for(UInt ch=0; ch10) { m_log2SaoOffsetScale[ch]=UInt(Clip3(0, m_internalBitDepth[ch]-10, Int(m_internalBitDepth[ch]-10 + 0.165*m_iQP - 3.22 + 0.5) ) ); } else { m_log2SaoOffsetScale[ch]=0; } } else { m_log2SaoOffsetScale[ch]=UInt(saoOffsetBitShift[ch]); } } assert(lumaLevelToDeltaQPMode=LUMALVL_TO_DQP_NUM_MODES) { exit(EXIT_FAILURE); } m_lumaLevelToDeltaQPMapping.mode=LumaLevelToDQPMode(lumaLevelToDeltaQPMode); if (m_lumaLevelToDeltaQPMapping.mode) { assert( cfg_lumaLeveltoDQPMappingLuma.values.size() == cfg_lumaLeveltoDQPMappingQP.values.size() ); m_lumaLevelToDeltaQPMapping.mapping.resize(cfg_lumaLeveltoDQPMappingLuma.values.size()); for(UInt i=0; i(cfg_lumaLeveltoDQPMappingLuma.values[i], cfg_lumaLeveltoDQPMappingQP.values[i]); } } // reading external dQP description from file if ( !m_dQPFileName.empty() ) { FILE* fpt=fopen( m_dQPFileName.c_str(), "r" ); if ( fpt ) { Int iValue; Int iPOC = 0; while ( iPOC < m_framesToBeEncoded ) { if ( fscanf(fpt, "%d", &iValue ) == EOF ) { break; } m_aidQP[ iPOC ] = iValue; iPOC++; } fclose(fpt); } } if( m_masteringDisplay.colourVolumeSEIEnabled ) { for(UInt idx=0; idx<6; idx++) { m_masteringDisplay.primaries[idx/2][idx%2] = UShort((cfg_DisplayPrimariesCode.values.size() > idx) ? cfg_DisplayPrimariesCode.values[idx] : 0); } for(UInt idx=0; idx<2; idx++) { m_masteringDisplay.whitePoint[idx] = UShort((cfg_DisplayWhitePointCode.values.size() > idx) ? cfg_DisplayWhitePointCode.values[idx] : 0); } } if( m_toneMappingInfoSEIEnabled && !m_toneMapCancelFlag ) { if( m_toneMapModelId == 2 && !cfg_startOfCodedInterval.values.empty() ) { const UInt num = 1u<< m_toneMapTargetBitDepth; m_startOfCodedInterval = new Int[num]; for(UInt i=0; i i ? cfg_startOfCodedInterval.values[i] : 0; } } else { m_startOfCodedInterval = NULL; } if( ( m_toneMapModelId == 3 ) && ( m_numPivots > 0 ) ) { if( !cfg_codedPivotValue.values.empty() && !cfg_targetPivotValue.values.empty() ) { m_codedPivotValue = new Int[m_numPivots]; m_targetPivotValue = new Int[m_numPivots]; for(UInt i=0; i i ? cfg_codedPivotValue.values [i] : 0; m_targetPivotValue[i] = cfg_targetPivotValue.values.size() > i ? cfg_targetPivotValue.values[i] : 0; } } } else { m_codedPivotValue = NULL; m_targetPivotValue = NULL; } } if( m_kneeSEIEnabled && !m_kneeFunctionInformationSEI.m_kneeFunctionCancelFlag ) { assert ( cfg_kneeSEINumKneePointsMinus1 >= 0 && cfg_kneeSEINumKneePointsMinus1 < 999 ); m_kneeFunctionInformationSEI.m_kneeSEIKneePointPairs.resize(cfg_kneeSEINumKneePointsMinus1+1); for(Int i=0; i<(cfg_kneeSEINumKneePointsMinus1+1); i++) { TEncCfg::TEncSEIKneeFunctionInformation::KneePointPair &kpp=m_kneeFunctionInformationSEI.m_kneeSEIKneePointPairs[i]; kpp.inputKneePoint = cfg_kneeSEIInputKneePointValue.values.size() > i ? cfg_kneeSEIInputKneePointValue.values[i] : 1; kpp.outputKneePoint = cfg_kneeSEIOutputKneePointValue.values.size() > i ? cfg_kneeSEIOutputKneePointValue.values[i] : 0; } } if ( m_omniViewportSEIEnabled && !m_omniViewportSEICancelFlag ) { assert ( m_omniViewportSEICntMinus1 >= 0 && m_omniViewportSEICntMinus1 < 16 ); m_omniViewportSEIAzimuthCentre.resize (m_omniViewportSEICntMinus1+1); m_omniViewportSEIElevationCentre.resize(m_omniViewportSEICntMinus1+1); m_omniViewportSEITiltCentre.resize (m_omniViewportSEICntMinus1+1); m_omniViewportSEIHorRange.resize (m_omniViewportSEICntMinus1+1); m_omniViewportSEIVerRange.resize (m_omniViewportSEICntMinus1+1); for(Int i=0; i<(m_omniViewportSEICntMinus1+1); i++) { m_omniViewportSEIAzimuthCentre[i] = cfg_omniViewportSEIAzimuthCentre .values.size() > i ? cfg_omniViewportSEIAzimuthCentre .values[i] : 0; m_omniViewportSEIElevationCentre[i] = cfg_omniViewportSEIElevationCentre.values.size() > i ? cfg_omniViewportSEIElevationCentre.values[i] : 0; m_omniViewportSEITiltCentre[i] = cfg_omniViewportSEITiltCentre .values.size() > i ? cfg_omniViewportSEITiltCentre .values[i] : 0; m_omniViewportSEIHorRange[i] = cfg_omniViewportSEIHorRange .values.size() > i ? cfg_omniViewportSEIHorRange .values[i] : 0; m_omniViewportSEIVerRange[i] = cfg_omniViewportSEIVerRange .values.size() > i ? cfg_omniViewportSEIVerRange .values[i] : 0; } } if(!m_rwpSEIRwpCancelFlag && m_rwpSEIEnabled) { assert ( m_rwpSEINumPackedRegions > 0 && m_rwpSEINumPackedRegions <= std::numeric_limits::max() ); assert (cfg_rwpSEIRwpTransformType.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIRwpGuardBandFlag.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIProjRegionWidth.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIProjRegionHeight.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIRwpSEIProjRegionTop.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIProjRegionLeft.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIPackedRegionWidth.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIPackedRegionHeight.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIPackedRegionTop.values.size() == m_rwpSEINumPackedRegions && cfg_rwpSEIPackedRegionLeft.values.size() == m_rwpSEINumPackedRegions); m_rwpSEIRwpTransformType.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpGuardBandFlag.resize(m_rwpSEINumPackedRegions); m_rwpSEIProjRegionWidth.resize(m_rwpSEINumPackedRegions); m_rwpSEIProjRegionHeight.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpSEIProjRegionTop.resize(m_rwpSEINumPackedRegions); m_rwpSEIProjRegionLeft.resize(m_rwpSEINumPackedRegions); m_rwpSEIPackedRegionWidth.resize(m_rwpSEINumPackedRegions); m_rwpSEIPackedRegionHeight.resize(m_rwpSEINumPackedRegions); m_rwpSEIPackedRegionTop.resize(m_rwpSEINumPackedRegions); m_rwpSEIPackedRegionLeft.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpLeftGuardBandWidth.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpRightGuardBandWidth.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpTopGuardBandHeight.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpBottomGuardBandHeight.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpGuardBandNotUsedForPredFlag.resize(m_rwpSEINumPackedRegions); m_rwpSEIRwpGuardBandType.resize(4*m_rwpSEINumPackedRegions); for( Int i=0; i < m_rwpSEINumPackedRegions; i++ ) { m_rwpSEIRwpTransformType[i] = cfg_rwpSEIRwpTransformType.values[i]; assert ( m_rwpSEIRwpTransformType[i] >= 0 && m_rwpSEIRwpTransformType[i] <= 7 ); m_rwpSEIRwpGuardBandFlag[i] = cfg_rwpSEIRwpGuardBandFlag.values[i]; m_rwpSEIProjRegionWidth[i] = cfg_rwpSEIProjRegionWidth.values[i]; m_rwpSEIProjRegionHeight[i] = cfg_rwpSEIProjRegionHeight.values[i]; m_rwpSEIRwpSEIProjRegionTop[i] = cfg_rwpSEIRwpSEIProjRegionTop.values[i]; m_rwpSEIProjRegionLeft[i] = cfg_rwpSEIProjRegionLeft.values[i]; m_rwpSEIPackedRegionWidth[i] = cfg_rwpSEIPackedRegionWidth.values[i]; m_rwpSEIPackedRegionHeight[i] = cfg_rwpSEIPackedRegionHeight.values[i]; m_rwpSEIPackedRegionTop[i] = cfg_rwpSEIPackedRegionTop.values[i]; m_rwpSEIPackedRegionLeft[i] = cfg_rwpSEIPackedRegionLeft.values[i]; if( m_rwpSEIRwpGuardBandFlag[i] ) { m_rwpSEIRwpLeftGuardBandWidth[i] = cfg_rwpSEIRwpLeftGuardBandWidth.values[i]; m_rwpSEIRwpRightGuardBandWidth[i] = cfg_rwpSEIRwpRightGuardBandWidth.values[i]; m_rwpSEIRwpTopGuardBandHeight[i] = cfg_rwpSEIRwpTopGuardBandHeight.values[i]; m_rwpSEIRwpBottomGuardBandHeight[i] = cfg_rwpSEIRwpBottomGuardBandHeight.values[i]; assert ( m_rwpSEIRwpLeftGuardBandWidth[i] > 0 || m_rwpSEIRwpRightGuardBandWidth[i] > 0 || m_rwpSEIRwpTopGuardBandHeight[i] >0 || m_rwpSEIRwpBottomGuardBandHeight[i] >0 ); m_rwpSEIRwpGuardBandNotUsedForPredFlag[i] = cfg_rwpSEIRwpGuardBandNotUsedForPredFlag.values[i]; for( Int j=0; j < 4; j++ ) { m_rwpSEIRwpGuardBandType[i*4 + j] = cfg_rwpSEIRwpGuardBandType.values[i*4 + j]; } } } } if (!m_fisheyeVideoInfoSEI.m_fisheyeCancelFlag && m_fisheyeVIdeoInfoSEIEnabled) { if (cfg_fviSEIFisheyeNumActiveAreasMinus1 < 0 || cfg_fviSEIFisheyeNumActiveAreasMinus1 > 3) { fprintf(stderr, "Bad number of FVI active areas\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCircularRegionCentreX.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI circular region centre X entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCircularRegionCentreY.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI circular region centre Y entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeRectRegionTop.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI rect region top entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeRectRegionLeft.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI rect region left entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeRectRegionWidth.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI rect region width entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeRectRegionHeight.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI rect region height entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCircularRegionRadius.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI circular region radius entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeSceneRadius.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI scene radius entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreAzimuth.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre azimuth entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreElevation.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre elevation entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreTilt.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre tilt entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreOffsetX.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre offsetX entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreOffsetY.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre offsetY entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeCameraCentreOffsetZ.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI camera centre offsetZ entries\n"); exit(EXIT_FAILURE); } if (cfg_fviSEIFisheyeFieldOfView.values.size() != cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1) { fprintf(stderr, "Bad number of FVI field of view entries\n"); exit(EXIT_FAILURE); } m_fisheyeVideoInfoSEI.m_fisheyeActiveAreas.resize(cfg_fviSEIFisheyeNumActiveAreasMinus1 + 1); for (std::size_t i = 0, extractPolynomialIdx = 0; i < m_fisheyeVideoInfoSEI.m_fisheyeActiveAreas.size(); i++) { TComSEIFisheyeVideoInfo::ActiveAreaInfo &info=m_fisheyeVideoInfoSEI.m_fisheyeActiveAreas[i]; info.m_fisheyeCircularRegionCentreX = cfg_fviSEIFisheyeCircularRegionCentreX.values[i]; info.m_fisheyeCircularRegionCentreY = cfg_fviSEIFisheyeCircularRegionCentreY.values[i]; info.m_fisheyeRectRegionTop = cfg_fviSEIFisheyeRectRegionTop.values[i]; info.m_fisheyeRectRegionLeft = cfg_fviSEIFisheyeRectRegionLeft.values[i]; info.m_fisheyeRectRegionWidth = cfg_fviSEIFisheyeRectRegionWidth.values[i]; info.m_fisheyeRectRegionHeight = cfg_fviSEIFisheyeRectRegionHeight.values[i]; info.m_fisheyeCircularRegionRadius = cfg_fviSEIFisheyeCircularRegionRadius.values[i]; info.m_fisheyeSceneRadius = cfg_fviSEIFisheyeSceneRadius.values[i]; // check rectangular region is within the conformance window. if ( (!( info.m_fisheyeRectRegionHeight >= 1 && m_confWinTop <= info.m_fisheyeRectRegionTop && info.m_fisheyeRectRegionTop + info.m_fisheyeRectRegionHeight < m_sourceHeight -m_confWinBottom ) ) || (!( info.m_fisheyeRectRegionWidth >= 1 && m_confWinLeft <= info.m_fisheyeRectRegionLeft && info.m_fisheyeRectRegionLeft + info.m_fisheyeRectRegionWidth < m_sourceWidth -m_confWinRight ) ) ) { fprintf(stderr, "Fisheye region is not within visible area\n"); exit (EXIT_FAILURE); } info.m_fisheyeCameraCentreAzimuth = cfg_fviSEIFisheyeCameraCentreAzimuth.values[i]; info.m_fisheyeCameraCentreElevation = cfg_fviSEIFisheyeCameraCentreElevation.values[i]; info.m_fisheyeCameraCentreTilt = cfg_fviSEIFisheyeCameraCentreTilt.values[i]; info.m_fisheyeCameraCentreOffsetX = cfg_fviSEIFisheyeCameraCentreOffsetX.values[i]; info.m_fisheyeCameraCentreOffsetY = cfg_fviSEIFisheyeCameraCentreOffsetY.values[i]; info.m_fisheyeCameraCentreOffsetZ = cfg_fviSEIFisheyeCameraCentreOffsetZ.values[i]; info.m_fisheyeFieldOfView = cfg_fviSEIFisheyeFieldOfView.values[i]; assert(cfg_fviSEIFisheyeNumPolynomialCoeffs.values[i] >= 0 && cfg_fviSEIFisheyeNumPolynomialCoeffs.values[i] <= 8); info.m_fisheyePolynomialCoeff.resize(cfg_fviSEIFisheyeNumPolynomialCoeffs.values[i]); for (Int j = 0; j < info.m_fisheyePolynomialCoeff.size(); j++) { assert(cfg_fviSEIFisheyePolynomialCoeff.values.size() > extractPolynomialIdx); info.m_fisheyePolynomialCoeff[j] = cfg_fviSEIFisheyePolynomialCoeff.values[extractPolynomialIdx++]; } } } #if SHUTTER_INTERVAL_SEI_PROCESSING m_ShutterFilterEnable = false; #endif #if SHUTTER_INTERVAL_SEI_MESSAGE if (m_siiSEIEnabled) { assert(m_siiSEITimeScale >= 0 && m_siiSEITimeScale <= MAX_UINT); UInt arraySize = (UInt)cfg_siiSEIInputNumUnitsInSI.values.size(); assert(arraySize > 0); if (arraySize > 1) { m_siiSEISubLayerNumUnitsInSI.resize(arraySize); for (Int i = 0; i < arraySize; i++) { m_siiSEISubLayerNumUnitsInSI[i] = cfg_siiSEIInputNumUnitsInSI.values[i]; assert(m_siiSEISubLayerNumUnitsInSI[i] >= 0 && m_siiSEISubLayerNumUnitsInSI[i] <= MAX_UINT); } } else { m_siiSEINumUnitsInShutterInterval = cfg_siiSEIInputNumUnitsInSI.values[0]; assert(m_siiSEINumUnitsInShutterInterval >= 0 && m_siiSEINumUnitsInShutterInterval <= MAX_UINT); } #if SHUTTER_INTERVAL_SEI_PROCESSING if (arraySize > 1 && m_siiSEISubLayerNumUnitsInSI[0] == 2 * m_siiSEISubLayerNumUnitsInSI[arraySize - 1]) { m_ShutterFilterEnable = true; const Double shutterAngle = 360.0; Double fpsHFR = (Double)m_iFrameRate, fpsLFR = (Double)m_iFrameRate / 2.0; UInt numUnitsHFR = (UInt)(((Double)m_siiSEITimeScale / fpsHFR) * (shutterAngle / 360.0)); UInt numUnitsLFR = (UInt)(((Double)m_siiSEITimeScale / fpsLFR) * (shutterAngle / 360.0)); for (Int i = 0; i < arraySize - 1; i++) m_siiSEISubLayerNumUnitsInSI[i] = numUnitsLFR; m_siiSEISubLayerNumUnitsInSI[arraySize - 1] = numUnitsHFR; } else { printf("Warning: SII-processing is applied for multiple shutter intervals and number of LFR units should be 2 times of number of HFR units\n"); } #endif } #endif if(m_timeCodeSEIEnabled) { for(Int i = 0; i < m_timeCodeSEINumTs && i < MAX_TIMECODE_SEI_SETS; i++) { m_timeSetArray[i].clockTimeStampFlag = cfg_timeCodeSeiTimeStampFlag .values.size()>i ? cfg_timeCodeSeiTimeStampFlag .values [i] : false; m_timeSetArray[i].numUnitFieldBasedFlag = cfg_timeCodeSeiNumUnitFieldBasedFlag.values.size()>i ? cfg_timeCodeSeiNumUnitFieldBasedFlag.values [i] : 0; m_timeSetArray[i].countingType = cfg_timeCodeSeiCountingType .values.size()>i ? cfg_timeCodeSeiCountingType .values [i] : 0; m_timeSetArray[i].fullTimeStampFlag = cfg_timeCodeSeiFullTimeStampFlag .values.size()>i ? cfg_timeCodeSeiFullTimeStampFlag .values [i] : 0; m_timeSetArray[i].discontinuityFlag = cfg_timeCodeSeiDiscontinuityFlag .values.size()>i ? cfg_timeCodeSeiDiscontinuityFlag .values [i] : 0; m_timeSetArray[i].cntDroppedFlag = cfg_timeCodeSeiCntDroppedFlag .values.size()>i ? cfg_timeCodeSeiCntDroppedFlag .values [i] : 0; m_timeSetArray[i].numberOfFrames = cfg_timeCodeSeiNumberOfFrames .values.size()>i ? cfg_timeCodeSeiNumberOfFrames .values [i] : 0; m_timeSetArray[i].secondsValue = cfg_timeCodeSeiSecondsValue .values.size()>i ? cfg_timeCodeSeiSecondsValue .values [i] : 0; m_timeSetArray[i].minutesValue = cfg_timeCodeSeiMinutesValue .values.size()>i ? cfg_timeCodeSeiMinutesValue .values [i] : 0; m_timeSetArray[i].hoursValue = cfg_timeCodeSeiHoursValue .values.size()>i ? cfg_timeCodeSeiHoursValue .values [i] : 0; m_timeSetArray[i].secondsFlag = cfg_timeCodeSeiSecondsFlag .values.size()>i ? cfg_timeCodeSeiSecondsFlag .values [i] : 0; m_timeSetArray[i].minutesFlag = cfg_timeCodeSeiMinutesFlag .values.size()>i ? cfg_timeCodeSeiMinutesFlag .values [i] : 0; m_timeSetArray[i].hoursFlag = cfg_timeCodeSeiHoursFlag .values.size()>i ? cfg_timeCodeSeiHoursFlag .values [i] : 0; m_timeSetArray[i].timeOffsetLength = cfg_timeCodeSeiTimeOffsetLength .values.size()>i ? cfg_timeCodeSeiTimeOffsetLength .values [i] : 0; m_timeSetArray[i].timeOffsetValue = cfg_timeCodeSeiTimeOffsetValue .values.size()>i ? cfg_timeCodeSeiTimeOffsetValue .values [i] : 0; } } #if JVET_X0048_X0103_FILM_GRAIN // Assigning the FGC SEI params from App to Lib if (!m_fgcSEIEnabled && m_fgcSEIAnalysisEnabled) { fprintf(stderr, "FGC SEI must be enabled in order to perform film grain analysis!\n"); exit(EXIT_FAILURE); } if (m_fgcSEIEnabled) { if (m_iQP < 17 && m_fgcSEIAnalysisEnabled == true) { fprintf(stderr, "***************************************************************************************************************\n"); fprintf(stderr, "** WARNING: Film Grain Estimation is disabled for Qp<17! FGC SEI will use default parameters for film grain! **\n"); fprintf(stderr, "***************************************************************************************************************\n"); m_fgcSEIAnalysisEnabled = false; } if (m_iIntraPeriod < 1) { fprintf(stderr, "*************************************************************************************\n"); fprintf(stderr, "** WARNING: For low delay configuration, FGC SEI is inserted for first frame only! **\n"); fprintf(stderr, "*************************************************************************************\n"); m_fgcSEIPerPictureSEI = false; m_fgcSEIPersistenceFlag = true; } else if (m_iIntraPeriod == 1) { fprintf(stderr, "*******************************************************************\n"); fprintf(stderr, "** WARNING: For Intra Period = 1, FGC SEI is inserted per frame! **\n"); fprintf(stderr, "*******************************************************************\n"); m_fgcSEIPerPictureSEI = true; m_fgcSEIPersistenceFlag = false; } if (!m_fgcSEIPerPictureSEI && !m_fgcSEIPersistenceFlag) { fprintf(stderr, "*************************************************************************************\n"); fprintf(stderr, "** WARNING: SEIPerPictureSEI is set to 0, SEIPersistenceFlag needs to be set to 1! **\n"); fprintf(stderr, "*************************************************************************************\n"); m_fgcSEIPersistenceFlag = true; } else if (m_fgcSEIPerPictureSEI && m_fgcSEIPersistenceFlag) { fprintf(stderr, "*************************************************************************************\n"); fprintf(stderr, "** WARNING: SEIPerPictureSEI is set to 1, SEIPersistenceFlag needs to be set to 0! **\n"); fprintf(stderr, "*************************************************************************************\n"); m_fgcSEIPersistenceFlag = false; } UInt numModelCtr; for (UInt c = 0; c <= 2; c++ ) { if (m_fgcSEICompModelPresent[c]) { numModelCtr = 0; for (UInt i = 0; i <= m_fgcSEINumIntensityIntervalMinus1[c]; i++) { m_fgcSEIIntensityIntervalLowerBound[c][i] = UChar((cfg_FgcSEIIntensityIntervalLowerBoundComp[c].values.size() > i) ? cfg_FgcSEIIntensityIntervalLowerBoundComp[c].values[i] : 0); m_fgcSEIIntensityIntervalUpperBound[c][i] = UChar((cfg_FgcSEIIntensityIntervalUpperBoundComp[c].values.size() > i) ? cfg_FgcSEIIntensityIntervalUpperBoundComp[c].values[i] : 0); for (UInt j = 0; j <= m_fgcSEINumModelValuesMinus1[c]; j++) { m_fgcSEICompModelValue[c][i][j] = UInt((cfg_FgcSEICompModelValueComp[c].values.size() > numModelCtr) ? cfg_FgcSEICompModelValueComp[c].values[numModelCtr] : 0); numModelCtr++; } } } } } #endif // check validity of input parameters xCheckParameter(); // compute actual CU depth with respect to config depth and max transform size UInt uiAddCUDepth = 0; while( (m_uiMaxCUWidth>>m_uiMaxCUDepth) > ( 1 << ( m_uiQuadtreeTULog2MinSize + uiAddCUDepth ) ) ) { uiAddCUDepth++; } m_uiMaxTotalCUDepth = m_uiMaxCUDepth + uiAddCUDepth + getMaxCUDepthOffset(m_chromaFormatIDC, m_uiQuadtreeTULog2MinSize); // if minimum TU larger than 4x4, allow for additional part indices for 4:2:2 SubTUs. m_uiLog2DiffMaxMinCodingBlockSize = m_uiMaxCUDepth - 1; // print-out parameters xPrintParameter(); return true; } // ==================================================================================================================== // Private member functions // ==================================================================================================================== Void TAppEncCfg::xCheckParameter() { if (m_decodedPictureHashSEIType==HASHTYPE_NONE) { fprintf(stderr, "******************************************************************\n"); fprintf(stderr, "** WARNING: --SEIDecodedPictureHash is now disabled by default. **\n"); fprintf(stderr, "** Automatic verification of decoded pictures by a **\n"); fprintf(stderr, "** decoder requires this option to be enabled. **\n"); fprintf(stderr, "******************************************************************\n"); } if( m_profile==Profile::NONE ) { fprintf(stderr, "***************************************************************************\n"); fprintf(stderr, "** WARNING: For conforming bitstreams a valid Profile value must be set! **\n"); fprintf(stderr, "***************************************************************************\n"); } if( m_level==Level::NONE ) { fprintf(stderr, "***************************************************************************\n"); fprintf(stderr, "** WARNING: For conforming bitstreams a valid Level value must be set! **\n"); fprintf(stderr, "***************************************************************************\n"); } Bool check_failed = false; /* abort if there is a fatal configuration problem */ #define xConfirmPara(a,b) check_failed |= confirmPara(a,b) xConfirmPara(m_bitstreamFileName.empty(), "A bitstream file name must be specified (BitstreamFile)"); const UInt maxBitDepth=(m_chromaFormatIDC==CHROMA_400) ? m_internalBitDepth[CHANNEL_TYPE_LUMA] : std::max(m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA]); xConfirmPara(m_bitDepthConstraint 3 || chromaFormatIdx>3) ? false : (validRExtProfileNames[intraIdx][bitDepthIdx][chromaFormatIdx] != UI_NONE); xConfirmPara(!bValidProfile, "Invalid intra constraint flag, bit depth constraint flag and chroma format constraint flag combination for a RExt profile"); const Bool bUsingGeneralRExtTools = m_transformSkipRotationEnabledFlag || m_transformSkipContextEnabledFlag || m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT] || m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT] || !m_enableIntraReferenceSmoothing || m_persistentRiceAdaptationEnabledFlag || m_log2MaxTransformSkipBlockSize!=2; const Bool bUsingChromaQPTool = m_diffCuChromaQpOffsetDepth >= 0; const Bool bUsingExtendedPrecision = m_extendedPrecisionProcessingFlag; xConfirmPara((m_chromaFormatConstraint==CHROMA_420 || m_chromaFormatConstraint==CHROMA_400) && bUsingChromaQPTool, "CU Chroma QP adjustment cannot be used for 4:0:0 or 4:2:0 RExt profiles"); xConfirmPara(m_bitDepthConstraint != 16 && bUsingExtendedPrecision, "Extended precision can only be used in 16-bit RExt profiles"); if (!(m_chromaFormatConstraint == CHROMA_400 && m_bitDepthConstraint == 16) && m_chromaFormatConstraint!=CHROMA_444) { xConfirmPara(bUsingGeneralRExtTools, "Combination of tools and profiles are not possible in the specified RExt profile."); } xConfirmPara( m_onePictureOnlyConstraintFlag && m_chromaFormatConstraint!=CHROMA_444, "chroma format constraint must be 4:4:4 when one-picture-only constraint flag is 1"); xConfirmPara( m_onePictureOnlyConstraintFlag && m_bitDepthConstraint != 8 && m_bitDepthConstraint != 16, "bit depth constraint must be 8 or 16 when one-picture-only constraint flag is 1"); xConfirmPara( m_onePictureOnlyConstraintFlag && m_framesToBeEncoded > 1, "Number of frames to be encoded must be 1 when one-picture-only constraint flag is 1."); if (!m_intraConstraintFlag && m_bitDepthConstraint==16 && m_chromaFormatConstraint==CHROMA_444) { fprintf(stderr, "********************************************************************************************************\n"); fprintf(stderr, "** WARNING: The RExt constraint flags describe a non standard combination (used for development only) **\n"); fprintf(stderr, "********************************************************************************************************\n"); } } else { xConfirmPara( m_chromaFormatConstraint != CHROMA_444, "chroma format constraint must be 4:4:4 in the High Throughput 4:4:4 16-bit Intra profile."); const UInt intraIdx = m_intraConstraintFlag ? 1:0; const UInt bitDepthIdx = (m_bitDepthConstraint == 8 ? 0 : (m_bitDepthConstraint ==10 ? 1 : (m_bitDepthConstraint == 14 ? 2 : (m_bitDepthConstraint == 16 ? 3 : 4 )))); const Bool bValidProfile = (bitDepthIdx > 3) ? false : (validRExtHighThroughPutProfileNames[intraIdx][bitDepthIdx] != UI_NONE); xConfirmPara(!bValidProfile, "Invalid intra constraint flag and bit depth constraint flag combination for a RExt high profile throughput profile"); if(bitDepthIdx < 2) { xConfirmPara((m_extendedPrecisionProcessingFlag || m_cabacBypassAlignmentEnabledFlag), "Invalid configuration for a RExt high throughput 8 and 10 bit profile"); } if(bitDepthIdx == 3) { xConfirmPara(!m_cabacBypassAlignmentEnabledFlag, "Cabac Bypass Alignment flag must be 1 in the High Throughput 4:4:4 16-bit Intra profile"); } else if(bitDepthIdx < 3) { xConfirmPara(!m_entropyCodingSyncEnabledFlag, "WPP flag must be 1 in the High Throughput 4:4:4 non 16-bit Intra profile"); } } } break; case Profile::MAIN: case Profile::MAIN10: case Profile::MAINSTILLPICTURE: { xConfirmPara(m_bitDepthConstraint!=((m_profile==Profile::MAIN10)?10:8), "BitDepthConstraint must be 8 for MAIN profile and 10 for MAIN10 profile."); xConfirmPara(m_chromaFormatConstraint!=CHROMA_420, "ChromaFormatConstraint must be 420 for non main-RExt profiles."); xConfirmPara(m_intraConstraintFlag==true, "IntraConstraintFlag must be false for non main_RExt profiles."); xConfirmPara(m_lowerBitRateConstraintFlag==false, "LowerBitrateConstraintFlag must be true for non main-RExt profiles."); xConfirmPara(m_profile == Profile::MAINSTILLPICTURE && m_framesToBeEncoded > 1, "Number of frames to be encoded must be 1 when main still picture profile is used."); xConfirmPara(m_crossComponentPredictionEnabledFlag==true, "CrossComponentPrediction must not be used for non main-RExt profiles."); xConfirmPara(m_log2MaxTransformSkipBlockSize!=2, "Transform Skip Log2 Max Size must be 2 for V1 profiles."); xConfirmPara(m_transformSkipRotationEnabledFlag==true, "UseResidualRotation must not be enabled for non main-RExt profiles."); xConfirmPara(m_transformSkipContextEnabledFlag==true, "UseSingleSignificanceMapContext must not be enabled for non main-RExt profiles."); xConfirmPara(m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT]==true, "ImplicitResidualDPCM must not be enabled for non main-RExt profiles."); xConfirmPara(m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT]==true, "ExplicitResidualDPCM must not be enabled for non main-RExt profiles."); xConfirmPara(m_persistentRiceAdaptationEnabledFlag==true, "GolombRiceParameterAdaption must not be enabled for non main-RExt profiles."); xConfirmPara(m_extendedPrecisionProcessingFlag==true, "UseExtendedPrecision must not be enabled for non main-RExt profiles."); xConfirmPara(m_highPrecisionOffsetsEnabledFlag==true, "UseHighPrecisionPredictionWeighting must not be enabled for non main-RExt profiles."); xConfirmPara(m_enableIntraReferenceSmoothing==false, "EnableIntraReferenceSmoothing must be enabled for non main-RExt profiles."); xConfirmPara(m_cabacBypassAlignmentEnabledFlag, "AlignCABACBeforeBypass cannot be enabled for non main-RExt profiles."); } break; case Profile::NONE: // Non-conforming configuration, so all settings are valid. break; default: xConfirmPara( 1, "Unknown profile selected."); break; } // check range of parameters xConfirmPara( m_inputBitDepth[CHANNEL_TYPE_LUMA ] < 8, "InputBitDepth must be at least 8" ); xConfirmPara( m_inputBitDepth[CHANNEL_TYPE_CHROMA] < 8, "InputBitDepthC must be at least 8" ); #if !RExt__HIGH_BIT_DEPTH_SUPPORT if (m_extendedPrecisionProcessingFlag) { for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { xConfirmPara((m_internalBitDepth[channelType] > 8) , "Model is not configured to support high enough internal accuracies - enable RExt__HIGH_BIT_DEPTH_SUPPORT to use increased precision internal data types etc..."); } } else { for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { xConfirmPara((m_internalBitDepth[channelType] > 12) , "Model is not configured to support high enough internal accuracies - enable RExt__HIGH_BIT_DEPTH_SUPPORT to use increased precision internal data types etc..."); } } #endif #if DPB_ENCODER_USAGE_CHECK ProfileLevelTierFeatures profileLevelTierFeatures; profileLevelTierFeatures.activate(m_profile, m_bitDepthConstraint, m_chromaFormatConstraint, m_intraConstraintFlag, m_onePictureOnlyConstraintFlag, m_level, m_levelTier, m_uiMaxCUWidth, m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA], m_chromaFormatIDC); #endif xConfirmPara( (m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA ] < m_inputBitDepth[CHANNEL_TYPE_LUMA ]), "MSB-extended bit depth for luma channel (--MSBExtendedBitDepth) must be greater than or equal to input bit depth for luma channel (--InputBitDepth)" ); xConfirmPara( (m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA] < m_inputBitDepth[CHANNEL_TYPE_CHROMA]), "MSB-extended bit depth for chroma channel (--MSBExtendedBitDepthC) must be greater than or equal to input bit depth for chroma channel (--InputBitDepthC)" ); xConfirmPara( m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA] > (m_internalBitDepth[CHANNEL_TYPE_LUMA ]<10?0:(m_internalBitDepth[CHANNEL_TYPE_LUMA ]-10)), "SaoLumaOffsetBitShift must be in the range of 0 to InternalBitDepth-10, inclusive"); xConfirmPara( m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA] > (m_internalBitDepth[CHANNEL_TYPE_CHROMA]<10?0:(m_internalBitDepth[CHANNEL_TYPE_CHROMA]-10)), "SaoChromaOffsetBitShift must be in the range of 0 to InternalBitDepthC-10, inclusive"); xConfirmPara( m_chromaFormatIDC >= NUM_CHROMA_FORMAT, "ChromaFormatIDC must be either 400, 420, 422 or 444" ); std::string sTempIPCSC="InputColourSpaceConvert must be empty, "+getListOfColourSpaceConverts(true); xConfirmPara( m_inputColourSpaceConvert >= NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS, sTempIPCSC.c_str() ); xConfirmPara( m_InputChromaFormatIDC >= NUM_CHROMA_FORMAT, "InputChromaFormatIDC must be either 400, 420, 422 or 444" ); xConfirmPara( m_iFrameRate <= 0, "Frame rate must be more than 1" ); xConfirmPara( m_temporalSubsampleRatio < 1, "Temporal subsample rate must be no less than 1" ); xConfirmPara( m_framesToBeEncoded <= 0, "Total Number Of Frames encoded must be more than 0" ); xConfirmPara( m_iGOPSize < 1 , "GOP Size must be greater or equal to 1" ); xConfirmPara( m_iGOPSize > 1 && m_iGOPSize % 2, "GOP Size must be a multiple of 2, if GOP Size is greater than 1" ); xConfirmPara( (m_iIntraPeriod > 0 && m_iIntraPeriod < m_iGOPSize) || m_iIntraPeriod == 0, "Intra period must be more than GOP size, or -1 , not 0" ); xConfirmPara( m_iDecodingRefreshType < 0 || m_iDecodingRefreshType > 3, "Decoding Refresh Type must be comprised between 0 and 3 included" ); if(m_iDecodingRefreshType == 3) { xConfirmPara( !m_recoveryPointSEIEnabled, "When using RecoveryPointSEI messages as RA points, recoveryPointSEI must be enabled" ); } if (m_isField) { if (!m_pictureTimingSEIEnabled) { fprintf(stderr, "****************************************************************************\n"); fprintf(stderr, "** WARNING: Picture Timing SEI should be enabled for field coding! **\n"); fprintf(stderr, "****************************************************************************\n"); } } if(m_crossComponentPredictionEnabledFlag && (m_chromaFormatIDC != CHROMA_444)) { fprintf(stderr, "****************************************************************************\n"); fprintf(stderr, "** WARNING: Cross-component prediction is specified for 4:4:4 format only **\n"); fprintf(stderr, "****************************************************************************\n"); m_crossComponentPredictionEnabledFlag = false; } if ( m_CUTransquantBypassFlagForce && m_bUseHADME ) { fprintf(stderr, "****************************************************************************\n"); fprintf(stderr, "** WARNING: --HadamardME has been disabled due to the enabling of **\n"); fprintf(stderr, "** --CUTransquantBypassFlagForce **\n"); fprintf(stderr, "****************************************************************************\n"); m_bUseHADME = false; // this has been disabled so that the lambda is calculated slightly differently for lossless modes (as a result of JCTVC-R0104). } xConfirmPara (m_log2MaxTransformSkipBlockSize < 2, "Transform Skip Log2 Max Size must be at least 2 (4x4)"); if (m_log2MaxTransformSkipBlockSize!=2 && m_useTransformSkipFast) { fprintf(stderr, "***************************************************************************\n"); fprintf(stderr, "** WARNING: Transform skip fast is enabled (which only tests NxN splits),**\n"); fprintf(stderr, "** but transform skip log2 max size is not 2 (4x4) **\n"); fprintf(stderr, "** It may be better to disable transform skip fast mode **\n"); fprintf(stderr, "***************************************************************************\n"); } xConfirmPara( m_iQP < -6 * (m_internalBitDepth[CHANNEL_TYPE_LUMA] - 8) || m_iQP > 51, "QP exceeds supported range (-QpBDOffsety to 51)" ); xConfirmPara( m_deblockingFilterMetric!=0 && (m_bLoopFilterDisable || m_loopFilterOffsetInPPS), "If DeblockingFilterMetric is non-zero then both LoopFilterDisable and LoopFilterOffsetInPPS must be 0"); xConfirmPara( m_loopFilterBetaOffsetDiv2 < -6 || m_loopFilterBetaOffsetDiv2 > 6, "Loop Filter Beta Offset div. 2 exceeds supported range (-6 to 6)"); xConfirmPara( m_loopFilterTcOffsetDiv2 < -6 || m_loopFilterTcOffsetDiv2 > 6, "Loop Filter Tc Offset div. 2 exceeds supported range (-6 to 6)"); xConfirmPara( m_iSearchRange < 0 , "Search Range must be more than 0" ); xConfirmPara( m_bipredSearchRange < 0 , "Bi-prediction refinement search range must be more than 0" ); xConfirmPara( m_minSearchWindow < 0, "Minimum motion search window size for the adaptive window ME must be greater than or equal to 0" ); xConfirmPara( m_iMaxDeltaQP > 7, "Absolute Delta QP exceeds supported range (0 to 7)" ); xConfirmPara(m_lumaLevelToDeltaQPMapping.mode && m_uiDeltaQpRD > 0, "Luma-level-based Delta QP cannot be used together with slice level multiple-QP optimization\n" ); xConfirmPara( m_iMaxCuDQPDepth > m_uiMaxCUDepth - 1, "Absolute depth for a minimum CuDQP exceeds maximum coding unit depth" ); xConfirmPara( m_cbQpOffset < -12, "Min. Chroma Cb QP Offset is -12" ); xConfirmPara( m_cbQpOffset > 12, "Max. Chroma Cb QP Offset is 12" ); xConfirmPara( m_crQpOffset < -12, "Min. Chroma Cr QP Offset is -12" ); xConfirmPara( m_crQpOffset > 12, "Max. Chroma Cr QP Offset is 12" ); xConfirmPara( m_iQPAdaptationRange <= 0, "QP Adaptation Range must be more than 0" ); if (m_iDecodingRefreshType == 2) { xConfirmPara( m_iIntraPeriod > 0 && m_iIntraPeriod <= m_iGOPSize , "Intra period must be larger than GOP size for periodic IDR pictures"); } xConfirmPara( m_uiMaxCUDepth < 1, "MaxPartitionDepth must be greater than zero"); xConfirmPara( (m_uiMaxCUWidth >> m_uiMaxCUDepth) < 4, "Minimum partition width size should be larger than or equal to 8"); xConfirmPara( (m_uiMaxCUHeight >> m_uiMaxCUDepth) < 4, "Minimum partition height size should be larger than or equal to 8"); xConfirmPara( m_uiMaxCUWidth < 16, "Maximum partition width size should be larger than or equal to 16"); xConfirmPara( m_uiMaxCUHeight < 16, "Maximum partition height size should be larger than or equal to 16"); xConfirmPara( (m_sourceWidth % (m_uiMaxCUWidth >> (m_uiMaxCUDepth-1)))!=0, "Resulting coded frame width must be a multiple of the minimum CU size"); xConfirmPara( (m_sourceHeight % (m_uiMaxCUHeight >> (m_uiMaxCUDepth-1)))!=0, "Resulting coded frame height must be a multiple of the minimum CU size"); xConfirmPara( m_uiQuadtreeTULog2MinSize < 2, "QuadtreeTULog2MinSize must be 2 or greater."); xConfirmPara( m_uiQuadtreeTULog2MaxSize > 5, "QuadtreeTULog2MaxSize must be 5 or smaller."); xConfirmPara( m_uiQuadtreeTULog2MaxSize < m_uiQuadtreeTULog2MinSize, "QuadtreeTULog2MaxSize must be greater than or equal to m_uiQuadtreeTULog2MinSize."); xConfirmPara( (1< m_uiMaxCUWidth, "QuadtreeTULog2MaxSize must be log2(maxCUSize) or smaller."); xConfirmPara( ( 1 << m_uiQuadtreeTULog2MinSize ) >= ( m_uiMaxCUWidth >> (m_uiMaxCUDepth-1)), "QuadtreeTULog2MinSize must not be greater than or equal to minimum CU size" ); xConfirmPara( ( 1 << m_uiQuadtreeTULog2MinSize ) >= ( m_uiMaxCUHeight >> (m_uiMaxCUDepth-1)), "QuadtreeTULog2MinSize must not be greater than or equal to minimum CU size" ); xConfirmPara( m_uiQuadtreeTUMaxDepthInter < 1, "QuadtreeTUMaxDepthInter must be greater than or equal to 1" ); xConfirmPara( m_uiMaxCUWidth < ( 1 << (m_uiQuadtreeTULog2MinSize + m_uiQuadtreeTUMaxDepthInter - 1) ), "QuadtreeTUMaxDepthInter must be less than or equal to the difference between log2(maxCUSize) and QuadtreeTULog2MinSize plus 1" ); xConfirmPara( m_uiQuadtreeTUMaxDepthIntra < 1, "QuadtreeTUMaxDepthIntra must be greater than or equal to 1" ); xConfirmPara( m_uiMaxCUWidth < ( 1 << (m_uiQuadtreeTULog2MinSize + m_uiQuadtreeTUMaxDepthIntra - 1) ), "QuadtreeTUMaxDepthInter must be less than or equal to the difference between log2(maxCUSize) and QuadtreeTULog2MinSize plus 1" ); xConfirmPara( m_maxNumMergeCand < 1, "MaxNumMergeCand must be 1 or greater."); xConfirmPara( m_maxNumMergeCand > 5, "MaxNumMergeCand must be 5 or smaller."); #if ADAPTIVE_QP_SELECTION xConfirmPara( m_bUseAdaptQpSelect == true && m_iQP < 0, "AdaptiveQpSelection must be disabled when QP < 0."); xConfirmPara( m_bUseAdaptQpSelect == true && (m_cbQpOffset !=0 || m_crQpOffset != 0 ), "AdaptiveQpSelection must be disabled when ChromaQpOffset is not equal to 0."); #endif if( m_usePCM) { for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { xConfirmPara(((m_MSBExtendedBitDepth[channelType] > m_internalBitDepth[channelType]) && m_bPCMInputBitDepthFlag), "PCM bit depth cannot be greater than internal bit depth (PCMInputBitDepthFlag cannot be used when InputBitDepth or MSBExtendedBitDepth > InternalBitDepth)"); } xConfirmPara( m_uiPCMLog2MinSize < 3, "PCMLog2MinSize must be 3 or greater."); xConfirmPara( m_uiPCMLog2MinSize > 5, "PCMLog2MinSize must be 5 or smaller."); xConfirmPara( m_pcmLog2MaxSize > 5, "PCMLog2MaxSize must be 5 or smaller."); xConfirmPara( m_pcmLog2MaxSize < m_uiPCMLog2MinSize, "PCMLog2MaxSize must be equal to or greater than m_uiPCMLog2MinSize."); } if (m_sliceMode!=NO_SLICES) { xConfirmPara( m_sliceArgument < 1 , "SliceArgument should be larger than or equal to 1" ); } if (m_sliceSegmentMode!=NO_SLICES) { xConfirmPara( m_sliceSegmentArgument < 1 , "SliceSegmentArgument should be larger than or equal to 1" ); } Bool tileFlag = (m_numTileColumnsMinus1 > 0 || m_numTileRowsMinus1 > 0 ); if (m_profile!=Profile::HIGHTHROUGHPUTREXT) { xConfirmPara( tileFlag && m_entropyCodingSyncEnabledFlag, "Tiles and entropy-coding-sync (Wavefronts) can not be applied together, except in the High Throughput Intra 4:4:4 16 profile"); } xConfirmPara( m_sourceWidth % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Picture width must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_sourceHeight % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Picture height must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_sourcePadding[0] % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Horizontal padding must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_sourcePadding[1] % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Vertical padding must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_confWinLeft % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Left conformance window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_confWinRight % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Right conformance window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_confWinTop % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Top conformance window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_confWinBottom % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Bottom conformance window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_defaultDisplayWindowFlag && !m_vuiParametersPresentFlag, "VUI needs to be enabled for default display window"); if (m_defaultDisplayWindowFlag) { xConfirmPara( m_defDispWinLeftOffset % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Left default display window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_defDispWinRightOffset % TComSPS::getWinUnitX(m_chromaFormatIDC) != 0, "Right default display window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_defDispWinTopOffset % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Top default display window offset must be an integer multiple of the specified chroma subsampling"); xConfirmPara( m_defDispWinBottomOffset % TComSPS::getWinUnitY(m_chromaFormatIDC) != 0, "Bottom default display window offset must be an integer multiple of the specified chroma subsampling"); } // max CU width and height should be power of 2 UInt ui = m_uiMaxCUWidth; while(ui) { ui >>= 1; if( (ui & 1) == 1) { xConfirmPara( ui != 1 , "Width should be 2^n"); } } ui = m_uiMaxCUHeight; while(ui) { ui >>= 1; if( (ui & 1) == 1) { xConfirmPara( ui != 1 , "Height should be 2^n"); } } /* if this is an intra-only sequence, ie IntraPeriod=1, don't verify the GOP structure * This permits the ability to omit a GOP structure specification */ if (m_iIntraPeriod == 1 && m_GOPList[0].m_POC == -1) { m_GOPList[0] = GOPEntry(); m_GOPList[0].m_QPFactor = 1; m_GOPList[0].m_betaOffsetDiv2 = 0; m_GOPList[0].m_tcOffsetDiv2 = 0; m_GOPList[0].m_POC = 1; m_GOPList[0].m_numRefPicsActive = 4; } else { xConfirmPara( m_intraConstraintFlag, "IntraConstraintFlag cannot be 1 for inter sequences"); } Bool verifiedGOP=false; Bool errorGOP=false; Int checkGOP=1; Int numRefs = m_isField ? 2 : 1; Int refList[MAX_NUM_REF_PICS+1]; refList[0]=0; if(m_isField) { refList[1] = 1; } Bool isOK[MAX_GOP]; for(Int i=0; i=0&&(m_iIntraPeriod%m_iGOPSize!=0), "Intra period must be a multiple of GOPSize, or -1" ); for(Int i=0; i 6, "Loop Filter Beta Offset div. 2 for one of the GOP entries exceeds supported range (-6 to 6)" ); xConfirmPara( (m_GOPList[i].m_tcOffsetDiv2 + m_loopFilterTcOffsetDiv2) < -6 || (m_GOPList[i].m_tcOffsetDiv2 + m_loopFilterTcOffsetDiv2) > 6, "Loop Filter Tc Offset div. 2 for one of the GOP entries exceeds supported range (-6 to 6)" ); } } for(Int i=0; i 12, "Cb QP Offset for one of the GOP entries exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_GOPList[i].m_CbQPoffset + m_cbQpOffset) > 12, "Cb QP Offset for one of the GOP entries, when combined with the PPS Cb offset, exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_GOPList[i].m_CrQPoffset ) > 12, "Cr QP Offset for one of the GOP entries exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_GOPList[i].m_CrQPoffset + m_crQpOffset) > 12, "Cr QP Offset for one of the GOP entries, when combined with the PPS Cr offset, exceeds supported range (-12 to 12)" ); } xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[0] ) > 12, "Intra/periodic Cb QP Offset exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[0] + m_cbQpOffset ) > 12, "Intra/periodic Cb QP Offset, when combined with the PPS Cb offset, exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[1] ) > 12, "Intra/periodic Cr QP Offset exceeds supported range (-12 to 12)" ); xConfirmPara( abs(m_sliceChromaQpOffsetIntraOrPeriodic[1] + m_crQpOffset ) > 12, "Intra/periodic Cr QP Offset, when combined with the PPS Cr offset, exceeds supported range (-12 to 12)" ); m_extraRPSs=0; //start looping through frames in coding order until we can verify that the GOP structure is correct. while(!verifiedGOP&&!errorGOP) { Int curGOP = (checkGOP-1)%m_iGOPSize; Int curPOC = ((checkGOP-1)/m_iGOPSize)*m_iGOPSize + m_GOPList[curGOP].m_POC; if(m_GOPList[curGOP].m_POC<0) { printf("\nError: found fewer Reference Picture Sets than GOPSize\n"); errorGOP=true; } else { //check that all reference pictures are available, or have a POC < 0 meaning they might be available in the next GOP. Bool beforeI = false; for(Int i = 0; i< m_GOPList[curGOP].m_numRefPics; i++) { Int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[i]; if(absPOC < 0) { beforeI=true; } else { Bool found=false; for(Int j=0; j 0) #if DPB_ENCODER_USAGE_CHECK assert(m_iGOPSize+m_extraRPSs < MAX_GOP); #endif m_GOPList[m_iGOPSize+m_extraRPSs]=m_GOPList[curGOP]; Int newRefs=0; for(Int i = 0; i< m_GOPList[curGOP].m_numRefPics; i++) { Int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[i]; if(absPOC>=0) { m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[newRefs]=m_GOPList[curGOP].m_referencePics[i]; m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[newRefs]=m_GOPList[curGOP].m_usedByCurrPic[i]; newRefs++; } } Int numPrefRefs = m_GOPList[curGOP].m_numRefPicsActive; for(Int offset = -1; offset>-checkGOP; offset--) { //step backwards in coding order and include any extra available pictures we might find useful to replace the ones with POC < 0. Int offGOP = (checkGOP-1+offset)%m_iGOPSize; Int offPOC = ((checkGOP-1+offset)/m_iGOPSize)*m_iGOPSize + m_GOPList[offGOP].m_POC; if(offPOC>=0&&m_GOPList[offGOP].m_temporalId<=m_GOPList[curGOP].m_temporalId) { Bool newRef=false; for(Int i=0; i0) { insertPoint = j; break; } } Int prev = offPOC-curPOC; Int prevUsed = m_GOPList[offGOP].m_temporalId<=m_GOPList[curGOP].m_temporalId; for(Int j=insertPoint; j=numPrefRefs) { break; } } m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefPics=newRefs; m_GOPList[m_iGOPSize+m_extraRPSs].m_POC = curPOC; if (m_extraRPSs == 0) { m_GOPList[m_iGOPSize+m_extraRPSs].m_interRPSPrediction = 0; m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefIdc = 0; } else { Int rIdx = m_iGOPSize + m_extraRPSs - 1; Int refPOC = m_GOPList[rIdx].m_POC; Int refPics = m_GOPList[rIdx].m_numRefPics; Int newIdc=0; for(Int i = 0; i<= refPics; i++) { Int deltaPOC = ((i != refPics)? m_GOPList[rIdx].m_referencePics[i] : 0); // check if the reference abs POC is >= 0 Int absPOCref = refPOC+deltaPOC; Int refIdc = 0; for (Int j = 0; j < m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefPics; j++) { if ( (absPOCref - curPOC) == m_GOPList[m_iGOPSize+m_extraRPSs].m_referencePics[j]) { if (m_GOPList[m_iGOPSize+m_extraRPSs].m_usedByCurrPic[j]) { refIdc = 1; } else { refIdc = 2; } } } m_GOPList[m_iGOPSize+m_extraRPSs].m_refIdc[newIdc]=refIdc; newIdc++; } m_GOPList[m_iGOPSize+m_extraRPSs].m_interRPSPrediction = 1; m_GOPList[m_iGOPSize+m_extraRPSs].m_numRefIdc = newIdc; m_GOPList[m_iGOPSize+m_extraRPSs].m_deltaRPS = refPOC - m_GOPList[m_iGOPSize+m_extraRPSs].m_POC; } curGOP=m_iGOPSize+m_extraRPSs; m_extraRPSs++; } numRefs=0; for(Int i = 0; i< m_GOPList[curGOP].m_numRefPics; i++) { Int absPOC = curPOC+m_GOPList[curGOP].m_referencePics[i]; if(absPOC >= 0) { refList[numRefs]=absPOC; numRefs++; } } refList[numRefs]=curPOC; numRefs++; } checkGOP++; } xConfirmPara(errorGOP,"Invalid GOP structure given"); m_maxTempLayer = 1; for(Int i=0; i= m_maxTempLayer) { m_maxTempLayer = m_GOPList[i].m_temporalId+1; } xConfirmPara(m_GOPList[i].m_sliceType!='B' && m_GOPList[i].m_sliceType!='P' && m_GOPList[i].m_sliceType!='I', "Slice type must be equal to B or P or I"); } for(Int i=0; i m_maxDecPicBuffering[m_GOPList[i].m_temporalId]) { m_maxDecPicBuffering[m_GOPList[i].m_temporalId] = m_GOPList[i].m_numRefPics + 1; } Int highestDecodingNumberWithLowerPOC = 0; for(Int j=0; j m_GOPList[i].m_POC) { numReorder++; } } if(numReorder > m_numReorderPics[m_GOPList[i].m_temporalId]) { m_numReorderPics[m_GOPList[i].m_temporalId] = numReorder; } } for(Int i=0; i m_maxDecPicBuffering[i] - 1) { m_maxDecPicBuffering[i] = m_numReorderPics[i] + 1; } // a lower layer can not have higher value of m_uiMaxDecPicBuffering than a higher layer if(m_maxDecPicBuffering[i+1] < m_maxDecPicBuffering[i]) { m_maxDecPicBuffering[i+1] = m_maxDecPicBuffering[i]; } } // the value of num_reorder_pics[ i ] shall be in the range of 0 to max_dec_pic_buffering[ i ] - 1, inclusive if(m_numReorderPics[MAX_TLAYER-1] > m_maxDecPicBuffering[MAX_TLAYER-1] - 1) { m_maxDecPicBuffering[MAX_TLAYER-1] = m_numReorderPics[MAX_TLAYER-1] + 1; } #if DPB_ENCODER_USAGE_CHECK // Check DPB Usage: Int dpbSize=profileLevelTierFeatures.getMaxDPBNumFrames(m_sourceWidth*m_sourceHeight); if (dpbSize!=-1) { Int dpbUsage=xDPBUsage(0); if (dpbUsage > dpbSize) { std::cout << "WARNING - DPB SIZE (" << dpbSize << " pictures) IS LIKELY TO HAVE BEEN EXCEEDED:\n"; xDPBUsage(&(std::cout)); } } #endif if(m_vuiParametersPresentFlag && m_bitstreamRestrictionFlag) { Int PicSizeInSamplesY = m_sourceWidth * m_sourceHeight; if(tileFlag) { Int maxTileWidth = 0; Int maxTileHeight = 0; Int widthInCU = (m_sourceWidth % m_uiMaxCUWidth) ? m_sourceWidth/m_uiMaxCUWidth + 1: m_sourceWidth/m_uiMaxCUWidth; Int heightInCU = (m_sourceHeight % m_uiMaxCUHeight) ? m_sourceHeight/m_uiMaxCUHeight + 1: m_sourceHeight/m_uiMaxCUHeight; if(m_tileUniformSpacingFlag) { maxTileWidth = m_uiMaxCUWidth*((widthInCU+m_numTileColumnsMinus1)/(m_numTileColumnsMinus1+1)); maxTileHeight = m_uiMaxCUHeight*((heightInCU+m_numTileRowsMinus1)/(m_numTileRowsMinus1+1)); // if only the last tile-row is one treeblock higher than the others // the maxTileHeight becomes smaller if the last row of treeblocks has lower height than the others if(!((heightInCU-1)%(m_numTileRowsMinus1+1))) { maxTileHeight = maxTileHeight - m_uiMaxCUHeight + (m_sourceHeight % m_uiMaxCUHeight); } // if only the last tile-column is one treeblock wider than the others // the maxTileWidth becomes smaller if the last column of treeblocks has lower width than the others if(!((widthInCU-1)%(m_numTileColumnsMinus1+1))) { maxTileWidth = maxTileWidth - m_uiMaxCUWidth + (m_sourceWidth % m_uiMaxCUWidth); } } else // not uniform spacing { if(m_numTileColumnsMinus1<1) { maxTileWidth = m_sourceWidth; } else { Int accColumnWidth = 0; for(Int col=0; col<(m_numTileColumnsMinus1); col++) { maxTileWidth = m_tileColumnWidth[col]>maxTileWidth ? m_tileColumnWidth[col]:maxTileWidth; accColumnWidth += m_tileColumnWidth[col]; } maxTileWidth = (widthInCU-accColumnWidth)>maxTileWidth ? m_uiMaxCUWidth*(widthInCU-accColumnWidth):m_uiMaxCUWidth*maxTileWidth; } if(m_numTileRowsMinus1<1) { maxTileHeight = m_sourceHeight; } else { Int accRowHeight = 0; for(Int row=0; row<(m_numTileRowsMinus1); row++) { maxTileHeight = m_tileRowHeight[row]>maxTileHeight ? m_tileRowHeight[row]:maxTileHeight; accRowHeight += m_tileRowHeight[row]; } maxTileHeight = (heightInCU-accRowHeight)>maxTileHeight ? m_uiMaxCUHeight*(heightInCU-accRowHeight):m_uiMaxCUHeight*maxTileHeight; } } Int maxSizeInSamplesY = maxTileWidth*maxTileHeight; m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/maxSizeInSamplesY-4; } else if(m_entropyCodingSyncEnabledFlag) { m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/((2*m_sourceHeight+m_sourceWidth)*m_uiMaxCUHeight)-4; } else if(m_sliceMode == FIXED_NUMBER_OF_CTU) { m_minSpatialSegmentationIdc = 4*PicSizeInSamplesY/(m_sliceArgument*m_uiMaxCUWidth*m_uiMaxCUHeight)-4; } else { m_minSpatialSegmentationIdc = 0; } } if (m_toneMappingInfoSEIEnabled) { xConfirmPara( m_toneMapCodedDataBitDepth < 8 || m_toneMapCodedDataBitDepth > 14 , "SEIToneMapCodedDataBitDepth must be in rage 8 to 14"); xConfirmPara( m_toneMapTargetBitDepth < 1 || (m_toneMapTargetBitDepth > 16 && m_toneMapTargetBitDepth < 255) , "SEIToneMapTargetBitDepth must be in rage 1 to 16 or equal to 255"); xConfirmPara( m_toneMapModelId < 0 || m_toneMapModelId > 4 , "SEIToneMapModelId must be in rage 0 to 4"); xConfirmPara( m_cameraIsoSpeedValue == 0, "SEIToneMapCameraIsoSpeedValue shall not be equal to 0"); xConfirmPara( m_exposureIndexValue == 0, "SEIToneMapExposureIndexValue shall not be equal to 0"); xConfirmPara( m_extendedRangeWhiteLevel < 100, "SEIToneMapExtendedRangeWhiteLevel should be greater than or equal to 100"); xConfirmPara( m_nominalBlackLevelLumaCodeValue >= m_nominalWhiteLevelLumaCodeValue, "SEIToneMapNominalWhiteLevelLumaCodeValue shall be greater than SEIToneMapNominalBlackLevelLumaCodeValue"); xConfirmPara( m_extendedWhiteLevelLumaCodeValue < m_nominalWhiteLevelLumaCodeValue, "SEIToneMapExtendedWhiteLevelLumaCodeValue shall be greater than or equal to SEIToneMapNominalWhiteLevelLumaCodeValue"); } if (m_kneeSEIEnabled && !m_kneeFunctionInformationSEI.m_kneeFunctionCancelFlag) { Int kneeSEINumKneePointsMinus1=Int(m_kneeFunctionInformationSEI.m_kneeSEIKneePointPairs.size())-1; xConfirmPara( kneeSEINumKneePointsMinus1 < 0 || kneeSEINumKneePointsMinus1 > 998, "SEIKneeFunctionNumKneePointsMinus1 must be in the range of 0 to 998"); for ( UInt i=0; i<=kneeSEINumKneePointsMinus1; i++ ) { TEncCfg::TEncSEIKneeFunctionInformation::KneePointPair &kpp=m_kneeFunctionInformationSEI.m_kneeSEIKneePointPairs[i]; xConfirmPara( kpp.inputKneePoint < 1 || kpp.inputKneePoint > 999, "SEIKneeFunctionInputKneePointValue must be in the range of 1 to 999"); xConfirmPara( kpp.outputKneePoint < 0 || kpp.outputKneePoint > 1000, "SEIKneeFunctionOutputKneePointValue must be in the range of 0 to 1000"); if ( i > 0 ) { TEncCfg::TEncSEIKneeFunctionInformation::KneePointPair &kppPrev=m_kneeFunctionInformationSEI.m_kneeSEIKneePointPairs[i-1]; xConfirmPara( kppPrev.inputKneePoint >= kpp.inputKneePoint, "The i-th SEIKneeFunctionInputKneePointValue must be greater than the (i-1)-th value"); xConfirmPara( kppPrev.outputKneePoint >= kpp.outputKneePoint, "The i-th SEIKneeFunctionOutputKneePointValue must be greater than or equal to the (i-1)-th value"); } } } if (m_chromaResamplingFilterSEIenabled) { xConfirmPara( (m_chromaFormatIDC == CHROMA_400 ), "chromaResamplingFilterSEI is not allowed to be present when ChromaFormatIDC is equal to zero (4:0:0)" ); xConfirmPara(m_vuiParametersPresentFlag && m_chromaLocInfoPresentFlag && (m_chromaSampleLocTypeTopField != m_chromaSampleLocTypeBottomField ), "When chromaResamplingFilterSEI is enabled, ChromaSampleLocTypeTopField has to be equal to ChromaSampleLocTypeBottomField" ); } if ( m_RCEnableRateControl ) { if ( m_RCForceIntraQP ) { if ( m_RCInitialQP == 0 ) { printf( "\nInitial QP for rate control is not specified. Reset not to use force intra QP!" ); m_RCForceIntraQP = false; } } xConfirmPara( m_uiDeltaQpRD > 0, "Rate control cannot be used together with slice level multiple-QP optimization!\n" ); #if DPB_ENCODER_USAGE_CHECK if ((m_RCCpbSaturationEnabled) && profileLevelTierFeatures.getCpbSizeInBits()!=0) { xConfirmPara(m_RCCpbSize > profileLevelTierFeatures.getCpbSizeInBits(), "RCCpbSize should be smaller than or equal to Max CPB size according to tier and level"); #else if ((m_RCCpbSaturationEnabled) && (m_level!=Level::NONE) && (m_profile!=Profile::NONE)) { #if JVET_X0079_MODIFIED_BITRATES UInt uiLevelIdx = (m_level / 30) * 4 + (UInt)((m_level % 30) / 3); #else UInt uiLevelIdx = (m_level / 10) + (UInt)((m_level % 10) / 3); // (m_level / 30)*3 + ((m_level % 10) / 3); #endif xConfirmPara(m_RCCpbSize > g_uiMaxCpbSize[m_levelTier][uiLevelIdx], "RCCpbSize should be smaller than or equal to Max CPB size according to tier and level"); #endif xConfirmPara(m_RCInitialCpbFullness > 1, "RCInitialCpbFullness should be smaller than or equal to 1"); } } else { xConfirmPara( m_RCCpbSaturationEnabled != 0, "Target bits saturation cannot be processed without Rate control" ); } if (m_vuiParametersPresentFlag) { xConfirmPara(m_RCTargetBitrate == 0, "A target bit rate is required to be set for VUI/HRD parameters."); if (m_RCCpbSize == 0) { printf ("Warning: CPB size is set equal to zero. Adjusting value to be equal to TargetBitrate!\n"); m_RCCpbSize = m_RCTargetBitrate; } } xConfirmPara(!m_TransquantBypassEnabledFlag && m_CUTransquantBypassFlagForce, "CUTransquantBypassFlagForce cannot be 1 when TransquantBypassEnableFlag is 0"); xConfirmPara(m_log2ParallelMergeLevel < 2, "Log2ParallelMergeLevel should be larger than or equal to 2"); if (m_framePackingSEIEnabled) { xConfirmPara(m_framePackingSEIType < 3 || m_framePackingSEIType > 5 , "SEIFramePackingType must be in rage 3 to 5"); } if (m_segmentedRectFramePackingSEIEnabled) { xConfirmPara(m_framePackingSEIEnabled , "SEISegmentedRectFramePacking must be 0 when SEIFramePacking is 1"); } if((m_numTileColumnsMinus1 <= 0) && (m_numTileRowsMinus1 <= 0) && m_tmctsSEIEnabled) { printf("Warning: SEITempMotionConstrainedTileSets is set to false to disable temporal motion-constrained tile sets SEI message because there are no tiles enabled.\n"); m_tmctsSEIEnabled = false; } #if MCTS_ENC_CHECK if ((m_tmctsSEIEnabled) && (m_tmctsSEITileConstraint) && (m_bLFCrossTileBoundaryFlag) ) { printf("Warning: Constrained Encoding for Temporal Motion Constrained Tile Sets is enabled. Disabling filtering across tile boundaries!\n"); m_bLFCrossTileBoundaryFlag = false; } #endif #if MCTS_EXTRACTION if ((m_tmctsSEIEnabled) && (m_tmctsSEITileConstraint) && (m_tmctsExtractionSEIEnabled) && (m_sliceSegmentMode != 3) && (m_sliceSegmentArgument != 1) ) { printf("Warning: SEITMCTSExtractionInfo is enabled. Enabling segmentation with one slice per tile."); m_sliceMode = FIXED_NUMBER_OF_TILES; m_sliceArgument = 1; } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_siiSEIEnabled && m_ShutterFilterEnable && m_maxTempLayer == 1 && m_maxDecPicBuffering[0] == 1) { printf("Warning: Shutter Interval SEI message processing is disabled for single TempLayer and single frame in DPB\n"); m_ShutterFilterEnable = false; } #endif if(m_timeCodeSEIEnabled) { xConfirmPara(m_timeCodeSEINumTs > MAX_TIMECODE_SEI_SETS, "Number of time sets cannot exceed 3"); } xConfirmPara(m_preferredTransferCharacteristics > 255, "transfer_characteristics_idc should not be greater than 255."); if( m_erpSEIEnabled && !m_erpSEICancelFlag ) { xConfirmPara( m_erpSEIGuardBandType < 0 || m_erpSEIGuardBandType > 8, "SEIEquirectangularprojectionGuardBandType must be in the range of 0 to 7"); xConfirmPara( (m_chromaFormatIDC == CHROMA_420 || m_chromaFormatIDC == CHROMA_422) && (m_erpSEILeftGuardBandWidth%2 == 1), "SEIEquirectangularprojectionLeftGuardBandWidth must be an even number for 4:2:0 or 4:2:2 chroma format"); xConfirmPara( (m_chromaFormatIDC == CHROMA_420 || m_chromaFormatIDC == CHROMA_422) && (m_erpSEIRightGuardBandWidth%2 == 1), "SEIEquirectangularprojectionRightGuardBandWidth must be an even number for 4:2:0 or 4:2:2 chroma format"); } if( m_sphereRotationSEIEnabled && !m_sphereRotationSEICancelFlag ) { xConfirmPara( m_sphereRotationSEIYaw < -(180<<16) || m_sphereRotationSEIYaw > (180<<16)-1, "SEISphereRotationYaw must be in the range of -11 796 480 to 11 796 479"); xConfirmPara( m_sphereRotationSEIPitch < -(90<<16) || m_sphereRotationSEIYaw > (90<<16), "SEISphereRotationPitch must be in the range of -5 898 240 to 5 898 240"); xConfirmPara( m_sphereRotationSEIRoll < -(180<<16) || m_sphereRotationSEIYaw > (180<<16)-1, "SEISphereRotationRoll must be in the range of -11 796 480 to 11 796 479"); xConfirmPara( m_erpSEICancelFlag == 1 && m_cmpSEICmpCancelFlag == 1, "erp_cancel_flag equal to 0 or cmp_cancel_flag equal to 0 must be present"); } if ( m_omniViewportSEIEnabled && !m_omniViewportSEICancelFlag ) { xConfirmPara( m_omniViewportSEIId < 0 || m_omniViewportSEIId > 1023, "SEIomniViewportId must be in the range of 0 to 1023"); xConfirmPara( m_omniViewportSEICntMinus1 < 0 || m_omniViewportSEICntMinus1 > 15, "SEIomniViewportCntMinus1 must be in the range of 0 to 15"); for ( UInt i=0; i<=m_omniViewportSEICntMinus1; i++ ) { xConfirmPara( m_omniViewportSEIAzimuthCentre[i] < -(180<<16) || m_omniViewportSEIAzimuthCentre[i] > (180<<16)-1, "SEIOmniViewportAzimuthCentre must be in the range of -11 796 480 to 11 796 479"); xConfirmPara( m_omniViewportSEIElevationCentre[i] < -(90<<16) || m_omniViewportSEIElevationCentre[i] > (90<<16), "SEIOmniViewportSEIElevationCentre must be in the range of -5 898 240 to 5 898 240"); xConfirmPara( m_omniViewportSEITiltCentre[i] < -(180<<16) || m_omniViewportSEITiltCentre[i] > (180<<16)-1, "SEIOmniViewportTiltCentre must be in the range of -11 796 480 to 11 796 479"); xConfirmPara( m_omniViewportSEIHorRange[i] < 1 || m_omniViewportSEIHorRange[i] > (360<<16), "SEIOmniViewportHorRange must be in the range of 1 to 360*2^16"); xConfirmPara( m_omniViewportSEIVerRange[i] < 1 || m_omniViewportSEIVerRange[i] > (180<<16), "SEIOmniViewportVerRange must be in the range of 1 to 180*2^16"); } } if (m_gopBasedTemporalFilterEnabled) { xConfirmPara(m_temporalSubsampleRatio != 1, "GOP Based Temporal Filter only support Temporal sub-sample ratio 1"); xConfirmPara(m_gopBasedTemporalFilterPastRefs <= 0 && m_gopBasedTemporalFilterFutureRefs <= 0, "Either TemporalFilterPastRefs or TemporalFilterFutureRefs must be larger than 0 when TemporalFilter is enabled"); if ((m_gopBasedTemporalFilterPastRefs != 0 && m_gopBasedTemporalFilterPastRefs != TF_DEFAULT_REFS) || (m_gopBasedTemporalFilterFutureRefs != 0 && m_gopBasedTemporalFilterFutureRefs != TF_DEFAULT_REFS)) { printf("Warning: Number of frames used for temporal prefilter is different from default.\n"); } } #if JVET_Y0077_BIM if (m_bimEnabled) { xConfirmPara(m_temporalSubsampleRatio != 1, "Block Importance Mapping only support Temporal sub-sample ratio 1"); } #endif #if EXTENSION_360_VIDEO check_failed |= m_ext360.verifyParameters(); #endif #undef xConfirmPara if (check_failed) { exit(EXIT_FAILURE); } } const TChar *profileToString(const Profile::Name profile) { static const UInt numberOfProfiles = sizeof(strToProfile)/sizeof(*strToProfile); for (UInt profileIndex = 0; profileIndex < numberOfProfiles; profileIndex++) { if (strToProfile[profileIndex].value == profile) { return strToProfile[profileIndex].str; } } //if we get here, we didn't find this profile in the list - so there is an error std::cerr << "ERROR: Unknown profile \"" << profile << "\" in profileToString" << std::endl; assert(false); exit(1); return ""; } #if DPB_ENCODER_USAGE_CHECK Int TAppEncCfg::xDPBUsage(std::ostream *pOs) { Int minimumOffset=0; // Calculate minimum delay caused by the gop structure - i.e. the biggest positive difference between the decoding and display order. for(Int gopEntry=0; gopEntry(minimumOffset, gopEntry-poc); } if (pOs) { (*pOs) << "POCs marked with 'r' are reference frames. '!' are awaiting output.\n"; } Int maxNumInDPB=0; for(Int gopEntry=0; gopEntry=0) { // 'n' is positive, so check that it has already been decoded within this GOP. bNeeded=false; for(Int i=0; i 3 || chromaFormatIdx>3) ? UI_NONE : validRExtProfileNames[intraIdx][bitDepthIdx][chromaFormatIdx]; } std::string rextSubProfile; if (validProfileName!=UI_NONE) { rextSubProfile=enumToString(strToUIProfileName, sizeof(strToUIProfileName)/sizeof(*strToUIProfileName), validProfileName); } if (rextSubProfile == "main_444_16") { rextSubProfile="main_444_16 [NON STANDARD]"; } printf("Profile : %s (%s)\n", profileToString(m_profile), (rextSubProfile.empty())?"INVALID REXT PROFILE":rextSubProfile.c_str() ); } else if (m_profile == Profile::HIGHTHROUGHPUTREXT) { UIProfileName validProfileName; const UInt intraIdx = m_intraConstraintFlag ? 1:0; const UInt bitDepthIdx = (m_bitDepthConstraint == 8 ? 0 : (m_bitDepthConstraint ==10 ? 1 : (m_bitDepthConstraint == 12 ? 2 : (m_bitDepthConstraint == 16 ? 3 : 4 )))); validProfileName = (bitDepthIdx > 3) ? UI_NONE : validRExtHighThroughPutProfileNames[intraIdx][bitDepthIdx]; std::string subProfile; if (validProfileName!=UI_NONE) { subProfile=enumToString(strToUIProfileName, sizeof(strToUIProfileName)/sizeof(*strToUIProfileName), validProfileName); } printf("Profile : %s (%s)\n", profileToString(m_profile), (subProfile.empty())?"INVALID HIGH THROUGHPUT REXT PROFILE":subProfile.c_str() ); } else if (m_profile == Profile::MAIN10 && m_onePictureOnlyConstraintFlag) { printf("Profile : %s (main10-still-picture)\n", profileToString(m_profile) ); } else { printf("Profile : %s\n", profileToString(m_profile) ); } printf("CU size / depth / total-depth : %d / %d / %d\n", m_uiMaxCUWidth, m_uiMaxCUDepth, m_uiMaxTotalCUDepth ); printf("RQT trans. size (min / max) : %d / %d\n", 1 << m_uiQuadtreeTULog2MinSize, 1 << m_uiQuadtreeTULog2MaxSize ); printf("Max RQT depth inter : %d\n", m_uiQuadtreeTUMaxDepthInter); printf("Max RQT depth intra : %d\n", m_uiQuadtreeTUMaxDepthIntra); printf("Min PCM size : %d\n", 1 << m_uiPCMLog2MinSize); printf("Motion search range : %d\n", m_iSearchRange ); printf("Intra period : %d\n", m_iIntraPeriod ); printf("Decoding refresh type : %d\n", m_iDecodingRefreshType ); if (m_qpIncrementAtSourceFrame.bPresent) { printf("QP : %d (incrementing internal QP at source frame %d)\n", m_iQP, m_qpIncrementAtSourceFrame.value ); } else { printf("QP : %d\n", m_iQP ); } printf("Max dQP signaling depth : %d\n", m_iMaxCuDQPDepth); printf("Cb QP Offset : %d\n", m_cbQpOffset ); printf("Cr QP Offset : %d\n", m_crQpOffset); printf("QP adaptation : %d (range=%d)\n", m_bUseAdaptiveQP, (m_bUseAdaptiveQP ? m_iQPAdaptationRange : 0) ); printf("GOP size : %d\n", m_iGOPSize ); printf("Input bit depth : (Y:%d, C:%d)\n", m_inputBitDepth[CHANNEL_TYPE_LUMA], m_inputBitDepth[CHANNEL_TYPE_CHROMA] ); printf("MSB-extended bit depth : (Y:%d, C:%d)\n", m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA], m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA] ); printf("Internal bit depth : (Y:%d, C:%d)\n", m_internalBitDepth[CHANNEL_TYPE_LUMA], m_internalBitDepth[CHANNEL_TYPE_CHROMA] ); printf("PCM sample bit depth : (Y:%d, C:%d)\n", m_bPCMInputBitDepthFlag ? m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA] : m_internalBitDepth[CHANNEL_TYPE_LUMA], m_bPCMInputBitDepthFlag ? m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA] : m_internalBitDepth[CHANNEL_TYPE_CHROMA] ); printf("Intra reference smoothing : %s\n", (m_enableIntraReferenceSmoothing ? "Enabled" : "Disabled") ); printf("diff_cu_chroma_qp_offset_depth : %d\n", m_diffCuChromaQpOffsetDepth); printf("extended_precision_processing_flag : %s\n", (m_extendedPrecisionProcessingFlag ? "Enabled" : "Disabled") ); printf("implicit_rdpcm_enabled_flag : %s\n", (m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT] ? "Enabled" : "Disabled") ); printf("explicit_rdpcm_enabled_flag : %s\n", (m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT] ? "Enabled" : "Disabled") ); printf("transform_skip_rotation_enabled_flag : %s\n", (m_transformSkipRotationEnabledFlag ? "Enabled" : "Disabled") ); printf("transform_skip_context_enabled_flag : %s\n", (m_transformSkipContextEnabledFlag ? "Enabled" : "Disabled") ); printf("cross_component_prediction_enabled_flag: %s\n", (m_crossComponentPredictionEnabledFlag ? (m_reconBasedCrossCPredictionEstimate ? "Enabled (reconstructed-residual-based estimate)" : "Enabled (encoder-side-residual-based estimate)") : "Disabled") ); printf("high_precision_offsets_enabled_flag : %s\n", (m_highPrecisionOffsetsEnabledFlag ? "Enabled" : "Disabled") ); printf("persistent_rice_adaptation_enabled_flag: %s\n", (m_persistentRiceAdaptationEnabledFlag ? "Enabled" : "Disabled") ); printf("cabac_bypass_alignment_enabled_flag : %s\n", (m_cabacBypassAlignmentEnabledFlag ? "Enabled" : "Disabled") ); if (m_bUseSAO) { printf("log2_sao_offset_scale_luma : %d\n", m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA]); printf("log2_sao_offset_scale_chroma : %d\n", m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA]); } switch (m_costMode) { case COST_STANDARD_LOSSY: printf("Cost function: : Lossy coding (default)\n"); break; case COST_SEQUENCE_LEVEL_LOSSLESS: printf("Cost function: : Sequence_level_lossless coding\n"); break; case COST_LOSSLESS_CODING: printf("Cost function: : Lossless coding with fixed QP of %d\n", LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP); break; case COST_MIXED_LOSSLESS_LOSSY_CODING: printf("Cost function: : Mixed_lossless_lossy coding with QP'=%d for lossless evaluation\n", LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME); break; default: printf("Cost function: : Unknown\n"); break; } printf("RateControl : %d\n", m_RCEnableRateControl ); printf("WPMethod : %d\n", Int(m_weightedPredictionMethod)); if(m_RCEnableRateControl) { printf("TargetBitrate : %d\n", m_RCTargetBitrate ); printf("KeepHierarchicalBit : %d\n", m_RCKeepHierarchicalBit ); printf("LCULevelRC : %d\n", m_RCLCULevelRC ); printf("UseLCUSeparateModel : %d\n", m_RCUseLCUSeparateModel ); printf("InitialQP : %d\n", m_RCInitialQP ); printf("ForceIntraQP : %d\n", m_RCForceIntraQP ); printf("CpbSaturation : %d\n", m_RCCpbSaturationEnabled ); if (m_RCCpbSaturationEnabled) { printf("CpbSize : %d\n", m_RCCpbSize); printf("InitalCpbFullness : %.2f\n", m_RCInitialCpbFullness); } } printf("Max Num Merge Candidates : %d\n", m_maxNumMergeCand); printf("\n"); printf("TOOL CFG: "); printf("IBD:%d ", ((m_internalBitDepth[CHANNEL_TYPE_LUMA] > m_MSBExtendedBitDepth[CHANNEL_TYPE_LUMA]) || (m_internalBitDepth[CHANNEL_TYPE_CHROMA] > m_MSBExtendedBitDepth[CHANNEL_TYPE_CHROMA]))); printf("HAD:%d ", m_bUseHADME ); printf("RDQ:%d ", m_useRDOQ ); printf("RDQTS:%d ", m_useRDOQTS ); printf("RDpenalty:%d ", m_rdPenalty ); printf("LQP:%d ", m_lumaLevelToDeltaQPMapping.mode ); printf("SQP:%d ", m_uiDeltaQpRD ); printf("ASR:%d ", m_bUseASR ); printf("MinSearchWindow:%d ", m_minSearchWindow ); printf("RestrictMESampling:%d ", m_bRestrictMESampling ); printf("FEN:%d ", Int(m_fastInterSearchMode) ); printf("ECU:%d ", m_bUseEarlyCU ); printf("FDM:%d ", m_useFastDecisionForMerge ); printf("CFM:%d ", m_bUseCbfFastMode ); printf("ESD:%d ", m_useEarlySkipDetection ); printf("RQT:%d ", 1 ); printf("TransformSkip:%d ", m_useTransformSkip ); printf("TransformSkipFast:%d ", m_useTransformSkipFast ); printf("TransformSkipLog2MaxSize:%d ", m_log2MaxTransformSkipBlockSize); printf("Slice: M=%d ", Int(m_sliceMode)); if (m_sliceMode!=NO_SLICES) { printf("A=%d ", m_sliceArgument); } printf("SliceSegment: M=%d ",m_sliceSegmentMode); if (m_sliceSegmentMode!=NO_SLICES) { printf("A=%d ", m_sliceSegmentArgument); } printf("CIP:%d ", m_bUseConstrainedIntraPred); printf("SAO:%d ", (m_bUseSAO)?(1):(0)); printf("PCM:%d ", (m_usePCM && (1< #include namespace po = df::program_options_lite; //! \ingroup TAppEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// encoder configuration class class TAppEncCfg { public: template struct OptionalValue { Bool bPresent; T value; OptionalValue() : bPresent(false), value() { } }; protected: // file I/O std::string m_inputFileName; ///< source file name std::string m_bitstreamFileName; ///< output bitstream file std::string m_reconFileName; ///< output reconstruction file #if SHUTTER_INTERVAL_SEI_PROCESSING Bool m_ShutterFilterEnable; ///< enable Pre-Filtering with Shutter Interval SEI std::string m_shutterIntervalPreFileName; ///< output Pre-Filtering video #endif // Lambda modifiers Double m_adLambdaModifier[ MAX_TLAYER ]; ///< Lambda modifier array for each temporal layer std::vector m_adIntraLambdaModifier; ///< Lambda modifier for Intra pictures, one for each temporal layer. If size>temporalLayer, then use [temporalLayer], else if size>0, use [size()-1], else use m_adLambdaModifier. Double m_dIntraQpFactor; ///< Intra Q Factor. If negative, use a default equation: 0.57*(1.0 - Clip3( 0.0, 0.5, 0.05*(Double)(isField ? (GopSize-1)/2 : GopSize-1) )) // source specification Int m_iFrameRate; ///< source frame-rates (Hz) UInt m_FrameSkip; ///< number of skipped frames from the beginning UInt m_temporalSubsampleRatio; ///< temporal subsample ratio, 2 means code every two frames Int m_sourceWidth; ///< source width in pixel Int m_sourceHeight; ///< source height in pixel (when interlaced = field height) Int m_inputFileWidth; ///< width of image in input file (this is equivalent to sourceWidth, if sourceWidth is not subsequently altered due to padding) Int m_inputFileHeight; ///< height of image in input file (this is equivalent to sourceHeight, if sourceHeight is not subsequently altered due to padding) Int m_sourceHeightOrg; ///< original source height in pixel (when interlaced = frame height) Bool m_isField; ///< enable field coding Bool m_isTopFieldFirst; Bool m_bEfficientFieldIRAPEnabled; ///< enable an efficient field IRAP structure. Bool m_bHarmonizeGopFirstFieldCoupleEnabled; Int m_conformanceWindowMode; Int m_confWinLeft; Int m_confWinRight; Int m_confWinTop; Int m_confWinBottom; Int m_sourcePadding[2]; ///< number of padded pixels for width and height Int m_framesToBeEncoded; ///< number of encoded frames Bool m_AccessUnitDelimiter; ///< add Access Unit Delimiter NAL units InputColourSpaceConversion m_inputColourSpaceConvert; ///< colour space conversion to apply to input video Bool m_snrInternalColourSpace; ///< if true, then no colour space conversion is applied for snr calculation, otherwise inverse of input is applied. Bool m_outputInternalColourSpace; ///< if true, then no colour space conversion is applied for reconstructed video, otherwise inverse of input is applied. ChromaFormat m_InputChromaFormatIDC; Bool m_printMSEBasedSequencePSNR; Bool m_printHexPsnr; Bool m_printFrameMSE; Bool m_printSequenceMSE; Bool m_printMSSSIM; Bool m_bXPSNREnableFlag; ///< xPSNR enable flag Double m_dXPSNRWeight[MAX_NUM_COMPONENT]; ///< xPSNR per component weights Bool m_cabacZeroWordPaddingEnabled; Bool m_bClipInputVideoToRec709Range; Bool m_bClipOutputVideoToRec709Range; // profile/level Profile::Name m_profile; Level::Tier m_levelTier; Level::Name m_level; UInt m_bitDepthConstraint; ChromaFormat m_chromaFormatConstraint; Bool m_intraConstraintFlag; Bool m_onePictureOnlyConstraintFlag; Bool m_lowerBitRateConstraintFlag; Bool m_progressiveSourceFlag; Bool m_interlacedSourceFlag; Bool m_nonPackedConstraintFlag; Bool m_frameOnlyConstraintFlag; // coding structure Int m_iIntraPeriod; ///< period of I-slice (random access period) Int m_iDecodingRefreshType; ///< random access type Int m_iGOPSize; ///< GOP size of hierarchical structure Bool m_bReWriteParamSetsFlag; ///< Flag to enable rewriting of parameter sets at random access points Int m_extraRPSs; ///< extra RPSs added to handle CRA GOPEntry m_GOPList[MAX_GOP]; ///< the coding structure entries from the config file Int m_numReorderPics[MAX_TLAYER]; ///< total number of reorder pictures Int m_maxDecPicBuffering[MAX_TLAYER]; ///< total number of pictures in the decoded picture buffer Bool m_crossComponentPredictionEnabledFlag; ///< flag enabling the use of cross-component prediction Bool m_reconBasedCrossCPredictionEstimate; ///< causes the alpha calculation in encoder search to be based on the decoded residual rather than the pre-transform encoder-side residual UInt m_log2SaoOffsetScale[MAX_NUM_CHANNEL_TYPE]; ///< number of bits for the upward bit shift operation on the decoded SAO offsets Bool m_useTransformSkip; ///< flag for enabling intra transform skipping Bool m_useTransformSkipFast; ///< flag for enabling fast intra transform skipping UInt m_log2MaxTransformSkipBlockSize; ///< transform-skip maximum size (minimum of 2) Bool m_transformSkipRotationEnabledFlag; ///< control flag for transform-skip/transquant-bypass residual rotation Bool m_transformSkipContextEnabledFlag; ///< control flag for transform-skip/transquant-bypass single significance map context Bool m_rdpcmEnabledFlag[NUMBER_OF_RDPCM_SIGNALLING_MODES];///< control flags for residual DPCM Bool m_enableAMP; Bool m_persistentRiceAdaptationEnabledFlag; ///< control flag for Golomb-Rice parameter adaptation over each slice Bool m_cabacBypassAlignmentEnabledFlag; // coding quality OptionalValue m_qpIncrementAtSourceFrame; ///< Optional source frame number at which all subsequent frames are to use an increased internal QP. Int m_iQP; ///< QP value of key-picture (integer) Int m_intraQPOffset; ///< QP offset for intra slice (integer) Bool m_lambdaFromQPEnable; ///< enable flag for QP:lambda fix std::string m_dQPFileName; ///< QP offset for each slice (initialized from external file) Int* m_aidQP; ///< array of slice QP values Int m_iMaxDeltaQP; ///< max. |delta QP| UInt m_uiDeltaQpRD; ///< dQP range for multi-pass slice QP optimization Int m_iMaxCuDQPDepth; ///< Max. depth for a minimum CuDQPSize (0:default) Int m_diffCuChromaQpOffsetDepth; ///< If negative, then do not apply chroma qp offsets. Bool m_bFastDeltaQP; ///< Fast Delta QP (false:default) Int m_cbQpOffset; ///< Chroma Cb QP Offset (0:default) Int m_crQpOffset; ///< Chroma Cr QP Offset (0:default) WCGChromaQPControl m_wcgChromaQpControl; ///< Wide-colour-gamut chroma QP control. UInt m_sliceChromaQpOffsetPeriodicity; ///< Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. Int m_sliceChromaQpOffsetIntraOrPeriodic[2/*Cb,Cr*/]; ///< Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. LumaLevelToDeltaQPMapping m_lumaLevelToDeltaQPMapping; ///< mapping from luma level to Delta QP. #if ADAPTIVE_QP_SELECTION Bool m_bUseAdaptQpSelect; #endif #if JVET_V0078 Bool m_bSmoothQPReductionEnable; Double m_dSmoothQPReductionThreshold; Double m_dSmoothQPReductionModelScale; Double m_dSmoothQPReductionModelOffset; Int m_iSmoothQPReductionPeriodicity; Int m_iSmoothQPReductionLimit; #endif TComSEIMasteringDisplay m_masteringDisplay; Bool m_bUseAdaptiveQP; ///< Flag for enabling QP adaptation based on a psycho-visual model Int m_iQPAdaptationRange; ///< dQP range by QP adaptation Int m_maxTempLayer; ///< Max temporal layer // coding unit (CU) definition // TODO: Remove MaxCUWidth/MaxCUHeight and replace with MaxCUSize. UInt m_uiMaxCUWidth; ///< max. CU width in pixel UInt m_uiMaxCUHeight; ///< max. CU height in pixel UInt m_uiMaxCUDepth; ///< max. CU depth (as specified by command line) UInt m_uiMaxTotalCUDepth; ///< max. total CU depth - includes depth of transform-block structure UInt m_uiLog2DiffMaxMinCodingBlockSize; ///< difference between largest and smallest CU depth // transfom unit (TU) definition UInt m_uiQuadtreeTULog2MaxSize; UInt m_uiQuadtreeTULog2MinSize; UInt m_uiQuadtreeTUMaxDepthInter; UInt m_uiQuadtreeTUMaxDepthIntra; // coding tools (bit-depth) Int m_inputBitDepth [MAX_NUM_CHANNEL_TYPE]; ///< bit-depth of input file Int m_outputBitDepth [MAX_NUM_CHANNEL_TYPE]; ///< bit-depth of output file Int m_MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE]; ///< bit-depth of input samples after MSB extension Int m_internalBitDepth[MAX_NUM_CHANNEL_TYPE]; ///< bit-depth codec operates at (input/output files will be converted) Bool m_extendedPrecisionProcessingFlag; Bool m_highPrecisionOffsetsEnabledFlag; //coding tools (chroma format) ChromaFormat m_chromaFormatIDC; // coding tools (PCM bit-depth) Bool m_bPCMInputBitDepthFlag; ///< 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth. // coding tool (SAO) Bool m_bUseSAO; Bool m_bTestSAODisableAtPictureLevel; Double m_saoEncodingRate; ///< When >0 SAO early picture termination is enabled for luma and chroma Double m_saoEncodingRateChroma; ///< The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma. Int m_maxNumOffsetsPerPic; ///< SAO maximun number of offset per picture Bool m_saoCtuBoundary; ///< SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas Bool m_resetEncoderStateAfterIRAP; ///< When true, encoder state will be reset following an IRAP. // coding tools (loop filter) Bool m_bLoopFilterDisable; ///< flag for using deblocking filter Bool m_loopFilterOffsetInPPS; ///< offset for deblocking filter in 0 = slice header, 1 = PPS Int m_loopFilterBetaOffsetDiv2; ///< beta offset for deblocking filter Int m_loopFilterTcOffsetDiv2; ///< tc offset for deblocking filter Int m_deblockingFilterMetric; ///< blockiness metric in encoder // coding tools (PCM) Bool m_usePCM; ///< flag for using IPCM UInt m_pcmLog2MaxSize; ///< log2 of maximum PCM block size UInt m_uiPCMLog2MinSize; ///< log2 of minimum PCM block size Bool m_bPCMFilterDisableFlag; ///< PCM filter disable flag Bool m_enableIntraReferenceSmoothing; ///< flag for enabling(default)/disabling intra reference smoothing/filtering // coding tools (encoder-only parameters) Bool m_bUseASR; ///< flag for using adaptive motion search range Bool m_bUseHADME; ///< flag for using HAD in sub-pel ME Bool m_useRDOQ; ///< flag for using RD optimized quantization Bool m_useRDOQTS; ///< flag for using RD optimized quantization for transform skip Bool m_useSelectiveRDOQ; ///< flag for using selective RDOQ Int m_rdPenalty; ///< RD-penalty for 32x32 TU for intra in non-intra slices (0: no RD-penalty, 1: RD-penalty, 2: maximum RD-penalty) Bool m_bDisableIntraPUsInInterSlices; ///< Flag for disabling intra predicted PUs in inter slices. MESearchMethod m_motionEstimationSearchMethod; Bool m_bRestrictMESampling; ///< Restrict sampling for the Selective ME Int m_iSearchRange; ///< ME search range Int m_bipredSearchRange; ///< ME search range for bipred refinement Int m_minSearchWindow; ///< ME minimum search window size for the Adaptive Window ME Bool m_bClipForBiPredMeEnabled; ///< Enables clipping for Bi-Pred ME. Bool m_bFastMEAssumingSmootherMVEnabled; ///< Enables fast ME assuming a smoother MV. FastInterSearchMode m_fastInterSearchMode; ///< Parameter that controls fast encoder settings Bool m_bUseEarlyCU; ///< flag for using Early CU setting Bool m_useFastDecisionForMerge; ///< flag for using Fast Decision Merge RD-Cost Bool m_bUseCbfFastMode; ///< flag for using Cbf Fast PU Mode Decision Bool m_useEarlySkipDetection; ///< flag for using Early SKIP Detection SliceConstraint m_sliceMode; Int m_sliceArgument; ///< argument according to selected slice mode SliceConstraint m_sliceSegmentMode; Int m_sliceSegmentArgument; ///< argument according to selected slice segment mode Bool m_bLFCrossSliceBoundaryFlag; ///< 1: filter across slice boundaries 0: do not filter across slice boundaries Bool m_bLFCrossTileBoundaryFlag; ///< 1: filter across tile boundaries 0: do not filter across tile boundaries Bool m_tileUniformSpacingFlag; Int m_numTileColumnsMinus1; Int m_numTileRowsMinus1; std::vector m_tileColumnWidth; std::vector m_tileRowHeight; Bool m_entropyCodingSyncEnabledFlag; Bool m_bUseConstrainedIntraPred; ///< flag for using constrained intra prediction Bool m_bFastUDIUseMPMEnabled; Bool m_bFastMEForGenBLowDelayEnabled; Bool m_bUseBLambdaForNonKeyLowDelayPictures; HashType m_decodedPictureHashSEIType; ///< Checksum mode for decoded picture hash SEI message Bool m_recoveryPointSEIEnabled; Bool m_bufferingPeriodSEIEnabled; Bool m_pictureTimingSEIEnabled; Bool m_toneMappingInfoSEIEnabled; Bool m_chromaResamplingFilterSEIenabled; Int m_chromaResamplingHorFilterIdc; Int m_chromaResamplingVerFilterIdc; Int m_toneMapId; Bool m_toneMapCancelFlag; Bool m_toneMapPersistenceFlag; Int m_toneMapCodedDataBitDepth; Int m_toneMapTargetBitDepth; Int m_toneMapModelId; Int m_toneMapMinValue; Int m_toneMapMaxValue; Int m_sigmoidMidpoint; Int m_sigmoidWidth; Int m_numPivots; Int m_cameraIsoSpeedIdc; Int m_cameraIsoSpeedValue; Int m_exposureIndexIdc; Int m_exposureIndexValue; Bool m_exposureCompensationValueSignFlag; Int m_exposureCompensationValueNumerator; Int m_exposureCompensationValueDenomIdc; Int m_refScreenLuminanceWhite; Int m_extendedRangeWhiteLevel; Int m_nominalBlackLevelLumaCodeValue; Int m_nominalWhiteLevelLumaCodeValue; Int m_extendedWhiteLevelLumaCodeValue; Int* m_startOfCodedInterval; Int* m_codedPivotValue; Int* m_targetPivotValue; Bool m_framePackingSEIEnabled; Int m_framePackingSEIType; Int m_framePackingSEIId; Int m_framePackingSEIQuincunx; Int m_framePackingSEIInterpretation; Bool m_segmentedRectFramePackingSEIEnabled; Bool m_segmentedRectFramePackingSEICancel; Int m_segmentedRectFramePackingSEIType; Bool m_segmentedRectFramePackingSEIPersistence; Int m_displayOrientationSEIAngle; Bool m_temporalLevel0IndexSEIEnabled; Bool m_gradualDecodingRefreshInfoEnabled; Int m_noDisplaySEITLayer; Bool m_decodingUnitInfoSEIEnabled; Bool m_SOPDescriptionSEIEnabled; Bool m_scalableNestingSEIEnabled; Bool m_tmctsSEIEnabled; #if MCTS_ENC_CHECK Bool m_tmctsSEITileConstraint; #endif #if MCTS_EXTRACTION Bool m_tmctsExtractionSEIEnabled; #endif Bool m_timeCodeSEIEnabled; Int m_timeCodeSEINumTs; TComSEITimeSet m_timeSetArray[MAX_TIMECODE_SEI_SETS]; Bool m_kneeSEIEnabled; TEncCfg::TEncSEIKneeFunctionInformation m_kneeFunctionInformationSEI; Int m_preferredTransferCharacteristics; UInt m_greenMetadataType; UInt m_xsdMetricType; Bool m_ccvSEIEnabled; Bool m_ccvSEICancelFlag; Bool m_ccvSEIPersistenceFlag; Bool m_ccvSEIPrimariesPresentFlag; Bool m_ccvSEIMinLuminanceValuePresentFlag; Bool m_ccvSEIMaxLuminanceValuePresentFlag; Bool m_ccvSEIAvgLuminanceValuePresentFlag; Double m_ccvSEIPrimariesX[MAX_NUM_COMPONENT]; // Int(32) Double m_ccvSEIPrimariesY[MAX_NUM_COMPONENT]; // Int(32) Double m_ccvSEIMinLuminanceValue; // UInt(32) Double m_ccvSEIMaxLuminanceValue; // UInt(32) Double m_ccvSEIAvgLuminanceValue; // UInt(32) Bool m_erpSEIEnabled; Bool m_erpSEICancelFlag; Bool m_erpSEIPersistenceFlag; Bool m_erpSEIGuardBandFlag; UInt m_erpSEIGuardBandType; UInt m_erpSEILeftGuardBandWidth; UInt m_erpSEIRightGuardBandWidth; Bool m_sphereRotationSEIEnabled; Bool m_sphereRotationSEICancelFlag; Bool m_sphereRotationSEIPersistenceFlag; Int m_sphereRotationSEIYaw; Int m_sphereRotationSEIPitch; Int m_sphereRotationSEIRoll; Bool m_omniViewportSEIEnabled; UInt m_omniViewportSEIId; Bool m_omniViewportSEICancelFlag; Bool m_omniViewportSEIPersistenceFlag; UInt m_omniViewportSEICntMinus1; std::vector m_omniViewportSEIAzimuthCentre; std::vector m_omniViewportSEIElevationCentre; std::vector m_omniViewportSEITiltCentre; std::vector m_omniViewportSEIHorRange; std::vector m_omniViewportSEIVerRange; Bool m_cmpSEIEnabled; Bool m_cmpSEICmpCancelFlag; Bool m_cmpSEICmpPersistenceFlag; Bool m_rwpSEIEnabled; Bool m_rwpSEIRwpCancelFlag; Bool m_rwpSEIRwpPersistenceFlag; Bool m_rwpSEIConstituentPictureMatchingFlag; Int m_rwpSEINumPackedRegions; Int m_rwpSEIProjPictureWidth; Int m_rwpSEIProjPictureHeight; Int m_rwpSEIPackedPictureWidth; Int m_rwpSEIPackedPictureHeight; std::vector m_rwpSEIRwpTransformType; std::vector m_rwpSEIRwpGuardBandFlag; std::vector m_rwpSEIProjRegionWidth; std::vector m_rwpSEIProjRegionHeight; std::vector m_rwpSEIRwpSEIProjRegionTop; std::vector m_rwpSEIProjRegionLeft; std::vector m_rwpSEIPackedRegionWidth; std::vector m_rwpSEIPackedRegionHeight; std::vector m_rwpSEIPackedRegionTop; std::vector m_rwpSEIPackedRegionLeft; std::vector m_rwpSEIRwpLeftGuardBandWidth; std::vector m_rwpSEIRwpRightGuardBandWidth; std::vector m_rwpSEIRwpTopGuardBandHeight; std::vector m_rwpSEIRwpBottomGuardBandHeight; std::vector m_rwpSEIRwpGuardBandNotUsedForPredFlag; std::vector m_rwpSEIRwpGuardBandType; Bool m_gopBasedTemporalFilterEnabled; ///< GOP-based Temporal Filter enable/disable Int m_gopBasedTemporalFilterPastRefs; Int m_gopBasedTemporalFilterFutureRefs; Int m_firstValidFrame; Int m_lastValidFrame; std::map m_gopBasedTemporalFilterStrengths; ///< Filter strength per frame for the GOP-based Temporal Filter #if JVET_Y0077_BIM Bool m_bimEnabled; #endif std::string m_arSEIFileRoot; Bool m_fisheyeVIdeoInfoSEIEnabled; TComSEIFisheyeVideoInfo m_fisheyeVideoInfoSEI; // weighted prediction Bool m_useWeightedPred; ///< Use of weighted prediction in P slices Bool m_useWeightedBiPred; ///< Use of bi-directional weighted prediction in B slices WeightedPredictionMethod m_weightedPredictionMethod; UInt m_log2ParallelMergeLevel; ///< Parallel merge estimation region UInt m_maxNumMergeCand; ///< Max number of merge candidates Int m_TMVPModeId; Bool m_signDataHidingEnabledFlag; Bool m_RCEnableRateControl; ///< enable rate control or not Int m_RCTargetBitrate; ///< target bitrate when rate control is enabled Int m_RCKeepHierarchicalBit; ///< 0: equal bit allocation; 1: fixed ratio bit allocation; 2: adaptive ratio bit allocation Bool m_RCLCULevelRC; ///< true: LCU level rate control; false: picture level rate control NOTE: code-tidy - rename to m_RCCtuLevelRC Bool m_RCUseLCUSeparateModel; ///< use separate R-lambda model at LCU level NOTE: code-tidy - rename to m_RCUseCtuSeparateModel Int m_RCInitialQP; ///< inital QP for rate control Bool m_RCForceIntraQP; ///< force all intra picture to use initial QP or not Bool m_RCCpbSaturationEnabled; ///< enable target bits saturation to avoid CPB overflow and underflow UInt m_RCCpbSize; ///< CPB size Double m_RCInitialCpbFullness; ///< initial CPB fullness ScalingListMode m_useScalingListId; ///< using quantization matrix std::string m_scalingListFileName; ///< quantization matrix file name Bool m_TransquantBypassEnabledFlag; ///< transquant_bypass_enabled_flag setting in PPS. Bool m_CUTransquantBypassFlagForce; ///< if transquant_bypass_enabled_flag, then, if true, all CU transquant bypass flags will be set to true. CostMode m_costMode; ///< Cost mode to use Bool m_recalculateQPAccordingToLambda; ///< recalculate QP value according to the lambda value Bool m_useStrongIntraSmoothing; ///< enable strong intra smoothing for 32x32 blocks where the reference samples are flat Int m_activeParameterSetsSEIEnabled; Bool m_vuiParametersPresentFlag; ///< enable generation of VUI parameters Bool m_aspectRatioInfoPresentFlag; ///< Signals whether aspect_ratio_idc is present Int m_aspectRatioIdc; ///< aspect_ratio_idc Int m_sarWidth; ///< horizontal size of the sample aspect ratio Int m_sarHeight; ///< vertical size of the sample aspect ratio Bool m_overscanInfoPresentFlag; ///< Signals whether overscan_appropriate_flag is present Bool m_overscanAppropriateFlag; ///< Indicates whether conformant decoded pictures are suitable for display using overscan Bool m_videoSignalTypePresentFlag; ///< Signals whether video_format, video_full_range_flag, and colour_description_present_flag are present Int m_videoFormat; ///< Indicates representation of pictures Bool m_videoFullRangeFlag; ///< Indicates the black level and range of luma and chroma signals Bool m_colourDescriptionPresentFlag; ///< Signals whether colour_primaries, transfer_characteristics and matrix_coefficients are present Int m_colourPrimaries; ///< Indicates chromaticity coordinates of the source primaries Int m_transferCharacteristics; ///< Indicates the opto-electronic transfer characteristics of the source Int m_matrixCoefficients; ///< Describes the matrix coefficients used in deriving luma and chroma from RGB primaries Bool m_chromaLocInfoPresentFlag; ///< Signals whether chroma_sample_loc_type_top_field and chroma_sample_loc_type_bottom_field are present Int m_chromaSampleLocTypeTopField; ///< Specifies the location of chroma samples for top field Int m_chromaSampleLocTypeBottomField; ///< Specifies the location of chroma samples for bottom field Bool m_neutralChromaIndicationFlag; ///< Indicates that the value of all decoded chroma samples is equal to 1<<(BitDepthCr-1) Bool m_defaultDisplayWindowFlag; ///< Indicates the presence of the default window parameters Int m_defDispWinLeftOffset; ///< Specifies the left offset from the conformance window of the default window Int m_defDispWinRightOffset; ///< Specifies the right offset from the conformance window of the default window Int m_defDispWinTopOffset; ///< Specifies the top offset from the conformance window of the default window Int m_defDispWinBottomOffset; ///< Specifies the bottom offset from the conformance window of the default window Bool m_frameFieldInfoPresentFlag; ///< Indicates that pic_struct values are present in picture timing SEI messages Bool m_pocProportionalToTimingFlag; ///< Indicates that the POC value is proportional to the output time w.r.t. first picture in CVS Int m_numTicksPocDiffOneMinus1; ///< Number of ticks minus 1 that for a POC difference of one Bool m_bitstreamRestrictionFlag; ///< Signals whether bitstream restriction parameters are present Bool m_tilesFixedStructureFlag; ///< Indicates that each active picture parameter set has the same values of the syntax elements related to tiles Bool m_motionVectorsOverPicBoundariesFlag; ///< Indicates that no samples outside the picture boundaries are used for inter prediction Int m_minSpatialSegmentationIdc; ///< Indicates the maximum size of the spatial segments in the pictures in the coded video sequence Int m_maxBytesPerPicDenom; ///< Indicates a number of bytes not exceeded by the sum of the sizes of the VCL NAL units associated with any coded picture Int m_maxBitsPerMinCuDenom; ///< Indicates an upper bound for the number of bits of coding_unit() data Int m_log2MaxMvLengthHorizontal; ///< Indicate the maximum absolute value of a decoded horizontal MV component in quarter-pel luma units Int m_log2MaxMvLengthVertical; ///< Indicate the maximum absolute value of a decoded vertical MV component in quarter-pel luma units std::string m_colourRemapSEIFileRoot; std::string m_regionalNestingSEIFileRoot; #if SHUTTER_INTERVAL_SEI_MESSAGE Bool m_siiSEIEnabled; UInt m_siiSEINumUnitsInShutterInterval; UInt m_siiSEITimeScale; std::vector m_siiSEISubLayerNumUnitsInSI; #endif #if SEI_ENCODER_CONTROL // film grain characterstics sei Bool m_fgcSEIEnabled; Bool m_fgcSEICancelFlag; Bool m_fgcSEIPersistenceFlag; UInt m_fgcSEIModelID; Bool m_fgcSEISepColourDescPresentFlag; UInt m_fgcSEIBlendingModeID; UInt m_fgcSEILog2ScaleFactor; Bool m_fgcSEICompModelPresent[MAX_NUM_COMPONENT]; #if JVET_X0048_X0103_FILM_GRAIN Bool m_fgcSEIAnalysisEnabled; std::string m_fgcSEIExternalMask; std::string m_fgcSEIExternalDenoised; Bool m_fgcSEIPerPictureSEI; UInt m_fgcSEINumIntensityIntervalMinus1[MAX_NUM_COMPONENT]; UInt m_fgcSEINumModelValuesMinus1[MAX_NUM_COMPONENT]; UInt m_fgcSEIIntensityIntervalLowerBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UInt m_fgcSEIIntensityIntervalUpperBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UInt m_fgcSEICompModelValue[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES][FG_MAX_NUM_MODEL_VALUES]; #endif // content light level SEI Bool m_cllSEIEnabled; UInt m_cllSEIMaxContentLevel; UInt m_cllSEIMaxPicAvgLevel; // ambient viewing environment sei Bool m_aveSEIEnabled; UInt m_aveSEIAmbientIlluminance; UInt m_aveSEIAmbientLightX; UInt m_aveSEIAmbientLightY; #endif std::string m_summaryOutFilename; ///< filename to use for producing summary output file. std::string m_summaryPicFilenameBase; ///< Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended. UInt m_summaryVerboseness; ///< Specifies the level of the verboseness of the text output. #if EXTENSION_360_VIDEO TExt360AppEncCfg m_ext360; friend class TExt360AppEncCfg; friend class TExt360AppEncTop; #endif #if JCTVC_AD0021_SEI_MANIFEST Bool m_SEIManifestSEIEnabled; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Bool m_SEIPrefixIndicationSEIEnabled; #endif // internal member functions Void xCheckParameter (); ///< check validity of configuration values Void xPrintParameter (); ///< print configuration values Void xPrintUsage (); ///< print usage #if DPB_ENCODER_USAGE_CHECK Int xDPBUsage(std::ostream *pOs); ///> Calculates maximum number of frames stored in DPB. Can optionally output usage to a stream #endif public: TAppEncCfg(); virtual ~TAppEncCfg(); public: Void create (); ///< create option handling class Void destroy (); ///< destroy option handling class Bool parseCfg ( Int argc, TChar* argv[] ); ///< parse configuration file to fill member variables };// END CLASS DEFINITION TAppEncCfg //! \} #endif // __TAPPENCCFG__ HM-HM-18.0/source/App/TAppEncoder/TAppEncTop.cpp000066400000000000000000001547051442026013100211220ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppEncTop.cpp \brief Encoder application class */ #include #include #include #include #include #include #include #include "TAppEncTop.h" #include "TLibEncoder/TEncTemporalFilter.h" #include "TLibEncoder/AnnexBwrite.h" #if EXTENSION_360_VIDEO #include "TAppEncHelper360/TExt360AppEncTop.h" #endif using namespace std; //! \ingroup TAppEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== TAppEncTop::TAppEncTop() { m_iFrameRcvd = 0; m_totalBytes = 0; m_essentialBytes = 0; } TAppEncTop::~TAppEncTop() { } Void TAppEncTop::xInitLibCfg() { TComVPS vps; vps.setMaxTLayers ( m_maxTempLayer ); if (m_maxTempLayer == 1) { vps.setTemporalNestingFlag(true); } vps.setMaxLayers ( 1 ); for(Int i = 0; i < MAX_TLAYER; i++) { vps.setNumReorderPics ( m_numReorderPics[i], i ); vps.setMaxDecPicBuffering ( m_maxDecPicBuffering[i], i ); } m_cTEncTop.setVPS(&vps); m_cTEncTop.setProfile ( m_profile); m_cTEncTop.setLevel ( m_levelTier, m_level); m_cTEncTop.setProgressiveSourceFlag ( m_progressiveSourceFlag); m_cTEncTop.setInterlacedSourceFlag ( m_interlacedSourceFlag); m_cTEncTop.setNonPackedConstraintFlag ( m_nonPackedConstraintFlag); m_cTEncTop.setFrameOnlyConstraintFlag ( m_frameOnlyConstraintFlag); m_cTEncTop.setBitDepthConstraintValue ( m_bitDepthConstraint ); m_cTEncTop.setChromaFormatConstraintValue ( m_chromaFormatConstraint ); m_cTEncTop.setIntraConstraintFlag ( m_intraConstraintFlag ); m_cTEncTop.setOnePictureOnlyConstraintFlag ( m_onePictureOnlyConstraintFlag ); m_cTEncTop.setLowerBitRateConstraintFlag ( m_lowerBitRateConstraintFlag ); m_cTEncTop.setPrintMSEBasedSequencePSNR ( m_printMSEBasedSequencePSNR); m_cTEncTop.setPrintHexPsnr ( m_printHexPsnr); m_cTEncTop.setPrintFrameMSE ( m_printFrameMSE); m_cTEncTop.setPrintSequenceMSE ( m_printSequenceMSE); m_cTEncTop.setPrintMSSSIM ( m_printMSSSIM ); m_cTEncTop.setXPSNREnableFlag ( m_bXPSNREnableFlag); for (Int id = 0 ; id < MAX_NUM_COMPONENT; id++) { m_cTEncTop.setXPSNRWeight ( m_dXPSNRWeight[id], ComponentID(id)); } #if SHUTTER_INTERVAL_SEI_PROCESSING m_cTEncTop.setShutterFilterFlag ( m_ShutterFilterEnable ); #endif m_cTEncTop.setCabacZeroWordPaddingEnabled ( m_cabacZeroWordPaddingEnabled ); m_cTEncTop.setFrameRate ( m_iFrameRate ); m_cTEncTop.setFrameSkip ( m_FrameSkip ); m_cTEncTop.setTemporalSubsampleRatio ( m_temporalSubsampleRatio ); m_cTEncTop.setSourceWidth ( m_sourceWidth ); m_cTEncTop.setSourceHeight ( m_sourceHeight ); m_cTEncTop.setConformanceWindow ( m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom ); m_cTEncTop.setFramesToBeEncoded ( m_framesToBeEncoded ); //====== Coding Structure ======== m_cTEncTop.setIntraPeriod ( m_iIntraPeriod ); m_cTEncTop.setDecodingRefreshType ( m_iDecodingRefreshType ); m_cTEncTop.setGOPSize ( m_iGOPSize ); m_cTEncTop.setReWriteParamSetsFlag ( m_bReWriteParamSetsFlag ); m_cTEncTop.setGopList ( m_GOPList ); m_cTEncTop.setExtraRPSs ( m_extraRPSs ); for(Int i = 0; i < MAX_TLAYER; i++) { m_cTEncTop.setNumReorderPics ( m_numReorderPics[i], i ); m_cTEncTop.setMaxDecPicBuffering ( m_maxDecPicBuffering[i], i ); } for( UInt uiLoop = 0; uiLoop < MAX_TLAYER; ++uiLoop ) { m_cTEncTop.setLambdaModifier ( uiLoop, m_adLambdaModifier[ uiLoop ] ); } m_cTEncTop.setIntraLambdaModifier ( m_adIntraLambdaModifier ); m_cTEncTop.setIntraQpFactor ( m_dIntraQpFactor ); m_cTEncTop.setQP ( m_iQP ); m_cTEncTop.setIntraQPOffset ( m_intraQPOffset ); m_cTEncTop.setLambdaFromQPEnable ( m_lambdaFromQPEnable ); m_cTEncTop.setSourcePadding ( m_sourcePadding ); m_cTEncTop.setAccessUnitDelimiter ( m_AccessUnitDelimiter ); m_cTEncTop.setMaxTempLayer ( m_maxTempLayer ); m_cTEncTop.setUseAMP( m_enableAMP ); //===== Slice ======== //====== Loop/Deblock Filter ======== m_cTEncTop.setLoopFilterDisable ( m_bLoopFilterDisable ); m_cTEncTop.setLoopFilterOffsetInPPS ( m_loopFilterOffsetInPPS ); m_cTEncTop.setLoopFilterBetaOffset ( m_loopFilterBetaOffsetDiv2 ); m_cTEncTop.setLoopFilterTcOffset ( m_loopFilterTcOffsetDiv2 ); m_cTEncTop.setDeblockingFilterMetric ( m_deblockingFilterMetric ); //====== Motion search ======== m_cTEncTop.setDisableIntraPUsInInterSlices ( m_bDisableIntraPUsInInterSlices ); m_cTEncTop.setMotionEstimationSearchMethod ( m_motionEstimationSearchMethod ); m_cTEncTop.setSearchRange ( m_iSearchRange ); m_cTEncTop.setBipredSearchRange ( m_bipredSearchRange ); m_cTEncTop.setClipForBiPredMeEnabled ( m_bClipForBiPredMeEnabled ); m_cTEncTop.setFastMEAssumingSmootherMVEnabled ( m_bFastMEAssumingSmootherMVEnabled ); m_cTEncTop.setMinSearchWindow ( m_minSearchWindow ); m_cTEncTop.setRestrictMESampling ( m_bRestrictMESampling ); //====== Quality control ======== m_cTEncTop.setMaxDeltaQP ( m_iMaxDeltaQP ); m_cTEncTop.setMaxCuDQPDepth ( m_iMaxCuDQPDepth ); m_cTEncTop.setDiffCuChromaQpOffsetDepth ( m_diffCuChromaQpOffsetDepth ); m_cTEncTop.setChromaCbQpOffset ( m_cbQpOffset ); m_cTEncTop.setChromaCrQpOffset ( m_crQpOffset ); m_cTEncTop.setWCGChromaQpControl ( m_wcgChromaQpControl ); m_cTEncTop.setSliceChromaOffsetQpIntraOrPeriodic ( m_sliceChromaQpOffsetPeriodicity, m_sliceChromaQpOffsetIntraOrPeriodic ); m_cTEncTop.setChromaFormatIdc ( m_chromaFormatIDC ); #if ADAPTIVE_QP_SELECTION m_cTEncTop.setUseAdaptQpSelect ( m_bUseAdaptQpSelect ); #endif #if JVET_V0078 m_cTEncTop.setSmoothQPReductionEnable (m_bSmoothQPReductionEnable); m_cTEncTop.setSmoothQPReductionThreshold (m_dSmoothQPReductionThreshold); m_cTEncTop.setSmoothQPReductionModelScale (m_dSmoothQPReductionModelScale); m_cTEncTop.setSmoothQPReductionModelOffset (m_dSmoothQPReductionModelOffset); m_cTEncTop.setSmoothQPReductionLimit (m_iSmoothQPReductionLimit); m_cTEncTop.setSmoothQPReductionPeriodicity (m_iSmoothQPReductionPeriodicity); #endif m_cTEncTop.setUseAdaptiveQP ( m_bUseAdaptiveQP ); m_cTEncTop.setQPAdaptationRange ( m_iQPAdaptationRange ); m_cTEncTop.setExtendedPrecisionProcessingFlag ( m_extendedPrecisionProcessingFlag ); m_cTEncTop.setHighPrecisionOffsetsEnabledFlag ( m_highPrecisionOffsetsEnabledFlag ); m_cTEncTop.setWeightedPredictionMethod( m_weightedPredictionMethod ); //====== Tool list ======== m_cTEncTop.setLumaLevelToDeltaQPControls ( m_lumaLevelToDeltaQPMapping ); m_cTEncTop.setDeltaQpRD( (m_costMode==COST_LOSSLESS_CODING) ? 0 : m_uiDeltaQpRD ); m_cTEncTop.setFastDeltaQp ( m_bFastDeltaQP ); m_cTEncTop.setUseASR ( m_bUseASR ); m_cTEncTop.setUseHADME ( m_bUseHADME ); m_cTEncTop.setdQPs ( m_aidQP ); m_cTEncTop.setUseRDOQ ( m_useRDOQ ); m_cTEncTop.setUseRDOQTS ( m_useRDOQTS ); m_cTEncTop.setUseSelectiveRDOQ ( m_useSelectiveRDOQ ); m_cTEncTop.setRDpenalty ( m_rdPenalty ); m_cTEncTop.setMaxCUWidth ( m_uiMaxCUWidth ); m_cTEncTop.setMaxCUHeight ( m_uiMaxCUHeight ); m_cTEncTop.setMaxTotalCUDepth ( m_uiMaxTotalCUDepth ); m_cTEncTop.setLog2DiffMaxMinCodingBlockSize ( m_uiLog2DiffMaxMinCodingBlockSize ); m_cTEncTop.setQuadtreeTULog2MaxSize ( m_uiQuadtreeTULog2MaxSize ); m_cTEncTop.setQuadtreeTULog2MinSize ( m_uiQuadtreeTULog2MinSize ); m_cTEncTop.setQuadtreeTUMaxDepthInter ( m_uiQuadtreeTUMaxDepthInter ); m_cTEncTop.setQuadtreeTUMaxDepthIntra ( m_uiQuadtreeTUMaxDepthIntra ); m_cTEncTop.setFastInterSearchMode ( m_fastInterSearchMode ); m_cTEncTop.setUseEarlyCU ( m_bUseEarlyCU ); m_cTEncTop.setUseFastDecisionForMerge ( m_useFastDecisionForMerge ); m_cTEncTop.setUseCbfFastMode ( m_bUseCbfFastMode ); m_cTEncTop.setUseEarlySkipDetection ( m_useEarlySkipDetection ); m_cTEncTop.setCrossComponentPredictionEnabledFlag ( m_crossComponentPredictionEnabledFlag ); m_cTEncTop.setUseReconBasedCrossCPredictionEstimate ( m_reconBasedCrossCPredictionEstimate ); m_cTEncTop.setLog2SaoOffsetScale ( CHANNEL_TYPE_LUMA , m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA] ); m_cTEncTop.setLog2SaoOffsetScale ( CHANNEL_TYPE_CHROMA, m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA] ); m_cTEncTop.setUseTransformSkip ( m_useTransformSkip ); m_cTEncTop.setUseTransformSkipFast ( m_useTransformSkipFast ); m_cTEncTop.setTransformSkipRotationEnabledFlag ( m_transformSkipRotationEnabledFlag ); m_cTEncTop.setTransformSkipContextEnabledFlag ( m_transformSkipContextEnabledFlag ); m_cTEncTop.setPersistentRiceAdaptationEnabledFlag ( m_persistentRiceAdaptationEnabledFlag ); m_cTEncTop.setCabacBypassAlignmentEnabledFlag ( m_cabacBypassAlignmentEnabledFlag ); m_cTEncTop.setLog2MaxTransformSkipBlockSize ( m_log2MaxTransformSkipBlockSize ); for (UInt signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++) { m_cTEncTop.setRdpcmEnabledFlag ( RDPCMSignallingMode(signallingModeIndex), m_rdpcmEnabledFlag[signallingModeIndex]); } m_cTEncTop.setUseConstrainedIntraPred ( m_bUseConstrainedIntraPred ); m_cTEncTop.setFastUDIUseMPMEnabled ( m_bFastUDIUseMPMEnabled ); m_cTEncTop.setFastMEForGenBLowDelayEnabled ( m_bFastMEForGenBLowDelayEnabled ); m_cTEncTop.setUseBLambdaForNonKeyLowDelayPictures ( m_bUseBLambdaForNonKeyLowDelayPictures ); m_cTEncTop.setPCMLog2MinSize ( m_uiPCMLog2MinSize); m_cTEncTop.setUsePCM ( m_usePCM ); // set internal bit-depth and constants for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { m_cTEncTop.setBitDepth((ChannelType)channelType, m_internalBitDepth[channelType]); m_cTEncTop.setPCMBitDepth((ChannelType)channelType, m_bPCMInputBitDepthFlag ? m_MSBExtendedBitDepth[channelType] : m_internalBitDepth[channelType]); #if JVET_X0048_X0103_FILM_GRAIN m_cTEncTop.setBitDepthInput((ChannelType)channelType, m_inputBitDepth[channelType]); #endif } m_cTEncTop.setPCMLog2MaxSize ( m_pcmLog2MaxSize); m_cTEncTop.setMaxNumMergeCand ( m_maxNumMergeCand ); //====== Weighted Prediction ======== m_cTEncTop.setUseWP ( m_useWeightedPred ); m_cTEncTop.setWPBiPred ( m_useWeightedBiPred ); //====== Parallel Merge Estimation ======== m_cTEncTop.setLog2ParallelMergeLevelMinus2 ( m_log2ParallelMergeLevel - 2 ); //====== Slice ======== m_cTEncTop.setSliceMode ( m_sliceMode ); m_cTEncTop.setSliceArgument ( m_sliceArgument ); //====== Dependent Slice ======== m_cTEncTop.setSliceSegmentMode ( m_sliceSegmentMode ); m_cTEncTop.setSliceSegmentArgument ( m_sliceSegmentArgument ); if(m_sliceMode == NO_SLICES ) { m_bLFCrossSliceBoundaryFlag = true; } m_cTEncTop.setLFCrossSliceBoundaryFlag ( m_bLFCrossSliceBoundaryFlag ); m_cTEncTop.setUseSAO ( m_bUseSAO ); m_cTEncTop.setTestSAODisableAtPictureLevel ( m_bTestSAODisableAtPictureLevel ); m_cTEncTop.setSaoEncodingRate ( m_saoEncodingRate ); m_cTEncTop.setSaoEncodingRateChroma ( m_saoEncodingRateChroma ); m_cTEncTop.setMaxNumOffsetsPerPic ( m_maxNumOffsetsPerPic); m_cTEncTop.setSaoCtuBoundary ( m_saoCtuBoundary); m_cTEncTop.setResetEncoderStateAfterIRAP ( m_resetEncoderStateAfterIRAP ); m_cTEncTop.setPCMInputBitDepthFlag ( m_bPCMInputBitDepthFlag); m_cTEncTop.setPCMFilterDisableFlag ( m_bPCMFilterDisableFlag); m_cTEncTop.setIntraSmoothingDisabledFlag (!m_enableIntraReferenceSmoothing ); m_cTEncTop.setDecodedPictureHashSEIType ( m_decodedPictureHashSEIType ); m_cTEncTop.setRecoveryPointSEIEnabled ( m_recoveryPointSEIEnabled ); m_cTEncTop.setBufferingPeriodSEIEnabled ( m_bufferingPeriodSEIEnabled ); m_cTEncTop.setPictureTimingSEIEnabled ( m_pictureTimingSEIEnabled ); m_cTEncTop.setToneMappingInfoSEIEnabled ( m_toneMappingInfoSEIEnabled ); m_cTEncTop.setTMISEIToneMapId ( m_toneMapId ); m_cTEncTop.setTMISEIToneMapCancelFlag ( m_toneMapCancelFlag ); m_cTEncTop.setTMISEIToneMapPersistenceFlag ( m_toneMapPersistenceFlag ); m_cTEncTop.setTMISEICodedDataBitDepth ( m_toneMapCodedDataBitDepth ); m_cTEncTop.setTMISEITargetBitDepth ( m_toneMapTargetBitDepth ); m_cTEncTop.setTMISEIModelID ( m_toneMapModelId ); m_cTEncTop.setTMISEIMinValue ( m_toneMapMinValue ); m_cTEncTop.setTMISEIMaxValue ( m_toneMapMaxValue ); m_cTEncTop.setTMISEISigmoidMidpoint ( m_sigmoidMidpoint ); m_cTEncTop.setTMISEISigmoidWidth ( m_sigmoidWidth ); m_cTEncTop.setTMISEIStartOfCodedInterva ( m_startOfCodedInterval ); m_cTEncTop.setTMISEINumPivots ( m_numPivots ); m_cTEncTop.setTMISEICodedPivotValue ( m_codedPivotValue ); m_cTEncTop.setTMISEITargetPivotValue ( m_targetPivotValue ); m_cTEncTop.setTMISEICameraIsoSpeedIdc ( m_cameraIsoSpeedIdc ); m_cTEncTop.setTMISEICameraIsoSpeedValue ( m_cameraIsoSpeedValue ); m_cTEncTop.setTMISEIExposureIndexIdc ( m_exposureIndexIdc ); m_cTEncTop.setTMISEIExposureIndexValue ( m_exposureIndexValue ); m_cTEncTop.setTMISEIExposureCompensationValueSignFlag ( m_exposureCompensationValueSignFlag ); m_cTEncTop.setTMISEIExposureCompensationValueNumerator ( m_exposureCompensationValueNumerator ); m_cTEncTop.setTMISEIExposureCompensationValueDenomIdc ( m_exposureCompensationValueDenomIdc ); m_cTEncTop.setTMISEIRefScreenLuminanceWhite ( m_refScreenLuminanceWhite ); m_cTEncTop.setTMISEIExtendedRangeWhiteLevel ( m_extendedRangeWhiteLevel ); m_cTEncTop.setTMISEINominalBlackLevelLumaCodeValue ( m_nominalBlackLevelLumaCodeValue ); m_cTEncTop.setTMISEINominalWhiteLevelLumaCodeValue ( m_nominalWhiteLevelLumaCodeValue ); m_cTEncTop.setTMISEIExtendedWhiteLevelLumaCodeValue ( m_extendedWhiteLevelLumaCodeValue ); m_cTEncTop.setChromaResamplingFilterHintEnabled ( m_chromaResamplingFilterSEIenabled ); m_cTEncTop.setChromaResamplingHorFilterIdc ( m_chromaResamplingHorFilterIdc ); m_cTEncTop.setChromaResamplingVerFilterIdc ( m_chromaResamplingVerFilterIdc ); m_cTEncTop.setFramePackingArrangementSEIEnabled ( m_framePackingSEIEnabled ); m_cTEncTop.setFramePackingArrangementSEIType ( m_framePackingSEIType ); m_cTEncTop.setFramePackingArrangementSEIId ( m_framePackingSEIId ); m_cTEncTop.setFramePackingArrangementSEIQuincunx ( m_framePackingSEIQuincunx ); m_cTEncTop.setFramePackingArrangementSEIInterpretation ( m_framePackingSEIInterpretation ); m_cTEncTop.setSegmentedRectFramePackingArrangementSEIEnabled ( m_segmentedRectFramePackingSEIEnabled ); m_cTEncTop.setSegmentedRectFramePackingArrangementSEICancel ( m_segmentedRectFramePackingSEICancel ); m_cTEncTop.setSegmentedRectFramePackingArrangementSEIType ( m_segmentedRectFramePackingSEIType ); m_cTEncTop.setSegmentedRectFramePackingArrangementSEIPersistence( m_segmentedRectFramePackingSEIPersistence ); m_cTEncTop.setDisplayOrientationSEIAngle ( m_displayOrientationSEIAngle ); m_cTEncTop.setTemporalLevel0IndexSEIEnabled ( m_temporalLevel0IndexSEIEnabled ); m_cTEncTop.setGradualDecodingRefreshInfoEnabled ( m_gradualDecodingRefreshInfoEnabled ); m_cTEncTop.setNoDisplaySEITLayer ( m_noDisplaySEITLayer ); m_cTEncTop.setDecodingUnitInfoSEIEnabled ( m_decodingUnitInfoSEIEnabled ); m_cTEncTop.setSOPDescriptionSEIEnabled ( m_SOPDescriptionSEIEnabled ); m_cTEncTop.setScalableNestingSEIEnabled ( m_scalableNestingSEIEnabled ); m_cTEncTop.setTMCTSSEIEnabled ( m_tmctsSEIEnabled ); #if MCTS_ENC_CHECK m_cTEncTop.setTMCTSSEITileConstraint ( m_tmctsSEITileConstraint ); #endif #if MCTS_EXTRACTION m_cTEncTop.setTMCTSExtractionSEIEnabled ( m_tmctsExtractionSEIEnabled); #endif m_cTEncTop.setTimeCodeSEIEnabled ( m_timeCodeSEIEnabled ); m_cTEncTop.setNumberOfTimeSets ( m_timeCodeSEINumTs ); for(Int i = 0; i < m_timeCodeSEINumTs; i++) { m_cTEncTop.setTimeSet(m_timeSetArray[i], i); } m_cTEncTop.setKneeSEIEnabled ( m_kneeSEIEnabled ); m_cTEncTop.setKneeFunctionInformationSEI ( m_kneeFunctionInformationSEI ); m_cTEncTop.setCcvSEIEnabled (m_ccvSEIEnabled); m_cTEncTop.setCcvSEICancelFlag (m_ccvSEICancelFlag); m_cTEncTop.setCcvSEIPersistenceFlag (m_ccvSEIPersistenceFlag); m_cTEncTop.setCcvSEIEnabled (m_ccvSEIEnabled); m_cTEncTop.setCcvSEICancelFlag (m_ccvSEICancelFlag); m_cTEncTop.setCcvSEIPersistenceFlag (m_ccvSEIPersistenceFlag); m_cTEncTop.setCcvSEIPrimariesPresentFlag (m_ccvSEIPrimariesPresentFlag); m_cTEncTop.setCcvSEIMinLuminanceValuePresentFlag (m_ccvSEIMinLuminanceValuePresentFlag); m_cTEncTop.setCcvSEIMaxLuminanceValuePresentFlag (m_ccvSEIMaxLuminanceValuePresentFlag); m_cTEncTop.setCcvSEIAvgLuminanceValuePresentFlag (m_ccvSEIAvgLuminanceValuePresentFlag); for(Int i = 0; i < MAX_NUM_COMPONENT; i++) { m_cTEncTop.setCcvSEIPrimariesX (m_ccvSEIPrimariesX[i], i); m_cTEncTop.setCcvSEIPrimariesY (m_ccvSEIPrimariesY[i], i); } m_cTEncTop.setCcvSEIMinLuminanceValue (m_ccvSEIMinLuminanceValue); m_cTEncTop.setCcvSEIMaxLuminanceValue (m_ccvSEIMaxLuminanceValue); m_cTEncTop.setCcvSEIAvgLuminanceValue (m_ccvSEIAvgLuminanceValue); m_cTEncTop.setErpSEIEnabled ( m_erpSEIEnabled ); m_cTEncTop.setErpSEICancelFlag ( m_erpSEICancelFlag ); m_cTEncTop.setErpSEIPersistenceFlag ( m_erpSEIPersistenceFlag ); m_cTEncTop.setErpSEIGuardBandFlag ( m_erpSEIGuardBandFlag ); m_cTEncTop.setErpSEIGuardBandType ( m_erpSEIGuardBandType ); m_cTEncTop.setErpSEILeftGuardBandWidth ( m_erpSEILeftGuardBandWidth ); m_cTEncTop.setErpSEIRightGuardBandWidth ( m_erpSEIRightGuardBandWidth ); m_cTEncTop.setSphereRotationSEIEnabled ( m_sphereRotationSEIEnabled ); m_cTEncTop.setSphereRotationSEICancelFlag ( m_sphereRotationSEICancelFlag ); m_cTEncTop.setSphereRotationSEIPersistenceFlag ( m_sphereRotationSEIPersistenceFlag ); m_cTEncTop.setSphereRotationSEIYaw ( m_sphereRotationSEIYaw ); m_cTEncTop.setSphereRotationSEIPitch ( m_sphereRotationSEIPitch ); m_cTEncTop.setSphereRotationSEIRoll ( m_sphereRotationSEIRoll ); m_cTEncTop.setOmniViewportSEIEnabled ( m_omniViewportSEIEnabled ); m_cTEncTop.setOmniViewportSEIId ( m_omniViewportSEIId ); m_cTEncTop.setOmniViewportSEICancelFlag ( m_omniViewportSEICancelFlag ); m_cTEncTop.setOmniViewportSEIPersistenceFlag ( m_omniViewportSEIPersistenceFlag ); m_cTEncTop.setOmniViewportSEICntMinus1 ( m_omniViewportSEICntMinus1 ); m_cTEncTop.setOmniViewportSEIAzimuthCentre ( m_omniViewportSEIAzimuthCentre ); m_cTEncTop.setOmniViewportSEIElevationCentre ( m_omniViewportSEIElevationCentre ); m_cTEncTop.setOmniViewportSEITiltCentre ( m_omniViewportSEITiltCentre ); m_cTEncTop.setOmniViewportSEIHorRange ( m_omniViewportSEIHorRange ); m_cTEncTop.setOmniViewportSEIVerRange ( m_omniViewportSEIVerRange ); m_cTEncTop.setGopBasedTemporalFilterEnabled ( m_gopBasedTemporalFilterEnabled ); #if JVET_Y0077_BIM m_cTEncTop.setBIM ( m_bimEnabled ); #endif m_cTEncTop.setCmpSEIEnabled (m_cmpSEIEnabled); m_cTEncTop.setCmpSEICmpCancelFlag (m_cmpSEICmpCancelFlag); m_cTEncTop.setCmpSEICmpPersistenceFlag (m_cmpSEICmpPersistenceFlag); m_cTEncTop.setRwpSEIEnabled (m_rwpSEIEnabled); m_cTEncTop.setRwpSEIRwpCancelFlag (m_rwpSEIRwpCancelFlag); m_cTEncTop.setRwpSEIRwpPersistenceFlag (m_rwpSEIRwpPersistenceFlag); m_cTEncTop.setRwpSEIConstituentPictureMatchingFlag (m_rwpSEIConstituentPictureMatchingFlag); m_cTEncTop.setRwpSEINumPackedRegions (m_rwpSEINumPackedRegions); m_cTEncTop.setRwpSEIProjPictureWidth (m_rwpSEIProjPictureWidth); m_cTEncTop.setRwpSEIProjPictureHeight (m_rwpSEIProjPictureHeight); m_cTEncTop.setRwpSEIPackedPictureWidth (m_rwpSEIPackedPictureWidth); m_cTEncTop.setRwpSEIPackedPictureHeight (m_rwpSEIPackedPictureHeight); m_cTEncTop.setRwpSEIRwpTransformType (m_rwpSEIRwpTransformType); m_cTEncTop.setRwpSEIRwpGuardBandFlag (m_rwpSEIRwpGuardBandFlag); m_cTEncTop.setRwpSEIProjRegionWidth (m_rwpSEIProjRegionWidth); m_cTEncTop.setRwpSEIProjRegionHeight (m_rwpSEIProjRegionHeight); m_cTEncTop.setRwpSEIRwpSEIProjRegionTop (m_rwpSEIRwpSEIProjRegionTop); m_cTEncTop.setRwpSEIProjRegionLeft (m_rwpSEIProjRegionLeft); m_cTEncTop.setRwpSEIPackedRegionWidth (m_rwpSEIPackedRegionWidth); m_cTEncTop.setRwpSEIPackedRegionHeight (m_rwpSEIPackedRegionHeight); m_cTEncTop.setRwpSEIPackedRegionTop (m_rwpSEIPackedRegionTop); m_cTEncTop.setRwpSEIPackedRegionLeft (m_rwpSEIPackedRegionLeft); m_cTEncTop.setRwpSEIRwpLeftGuardBandWidth (m_rwpSEIRwpLeftGuardBandWidth); m_cTEncTop.setRwpSEIRwpRightGuardBandWidth (m_rwpSEIRwpRightGuardBandWidth); m_cTEncTop.setRwpSEIRwpTopGuardBandHeight (m_rwpSEIRwpTopGuardBandHeight); m_cTEncTop.setRwpSEIRwpBottomGuardBandHeight (m_rwpSEIRwpBottomGuardBandHeight); m_cTEncTop.setRwpSEIRwpGuardBandNotUsedForPredFlag (m_rwpSEIRwpGuardBandNotUsedForPredFlag); m_cTEncTop.setRwpSEIRwpGuardBandType (m_rwpSEIRwpGuardBandType); #if SHUTTER_INTERVAL_SEI_MESSAGE m_cTEncTop.setSiiSEIEnabled (m_siiSEIEnabled); m_cTEncTop.setSiiSEINumUnitsInShutterInterval (m_siiSEINumUnitsInShutterInterval); m_cTEncTop.setSiiSEITimeScale (m_siiSEITimeScale); m_cTEncTop.setSiiSEISubLayerNumUnitsInSI (m_siiSEISubLayerNumUnitsInSI); #endif #if SEI_ENCODER_CONTROL // film grain charcteristics m_cTEncTop.setFilmGrainCharactersticsSEIEnabled (m_fgcSEIEnabled); m_cTEncTop.setFilmGrainCharactersticsSEICancelFlag (m_fgcSEICancelFlag); m_cTEncTop.setFilmGrainCharactersticsSEIPersistenceFlag (m_fgcSEIPersistenceFlag); m_cTEncTop.setFilmGrainCharactersticsSEIModelID ((UChar)m_fgcSEIModelID); m_cTEncTop.setFilmGrainCharactersticsSEISepColourDescPresent (m_fgcSEISepColourDescPresentFlag); m_cTEncTop.setFilmGrainCharactersticsSEIBlendingModeID ((UChar)m_fgcSEIBlendingModeID); m_cTEncTop.setFilmGrainCharactersticsSEILog2ScaleFactor ((UChar)m_fgcSEILog2ScaleFactor); #if JVET_X0048_X0103_FILM_GRAIN m_cTEncTop.setFilmGrainAnalysisEnabled (m_fgcSEIAnalysisEnabled); m_cTEncTop.setFilmGrainExternalMask (m_fgcSEIExternalMask); m_cTEncTop.setFilmGrainExternalDenoised (m_fgcSEIExternalDenoised); m_cTEncTop.setFilmGrainCharactersticsSEIPerPictureSEI (m_fgcSEIPerPictureSEI); #endif for (Int i = 0; i < MAX_NUM_COMPONENT; i++) { m_cTEncTop.setFGCSEICompModelPresent (m_fgcSEICompModelPresent[i], i); #if JVET_X0048_X0103_FILM_GRAIN if (m_fgcSEICompModelPresent[i]) { m_cTEncTop.setFGCSEINumIntensityIntervalMinus1 ((UChar)m_fgcSEINumIntensityIntervalMinus1[i], i); m_cTEncTop.setFGCSEINumModelValuesMinus1 ((UChar)m_fgcSEINumModelValuesMinus1[i], i); for (UInt j = 0; j <= m_fgcSEINumIntensityIntervalMinus1[i]; j++) { m_cTEncTop.setFGCSEIIntensityIntervalLowerBound ((UChar)m_fgcSEIIntensityIntervalLowerBound[i][j], i, j); m_cTEncTop.setFGCSEIIntensityIntervalUpperBound ((UChar)m_fgcSEIIntensityIntervalUpperBound[i][j], i, j); for (UInt k = 0; k <= m_fgcSEINumModelValuesMinus1[i]; k++) { m_cTEncTop.setFGCSEICompModelValue (m_fgcSEICompModelValue[i][j][k], i, j, k); } } } #endif } // content light level m_cTEncTop.setCLLSEIEnabled (m_cllSEIEnabled); m_cTEncTop.setCLLSEIMaxContentLightLevel ((UShort)m_cllSEIMaxContentLevel); m_cTEncTop.setCLLSEIMaxPicAvgLightLevel ((UShort)m_cllSEIMaxPicAvgLevel); // ambient viewing enviornment m_cTEncTop.setAmbientViewingEnvironmentSEIEnabled (m_aveSEIEnabled); m_cTEncTop.setAmbientViewingEnvironmentSEIIlluminance (m_aveSEIAmbientIlluminance); m_cTEncTop.setAmbientViewingEnvironmentSEIAmbientLightX ((UShort)m_aveSEIAmbientLightX); m_cTEncTop.setAmbientViewingEnvironmentSEIAmbientLightY ((UShort)m_aveSEIAmbientLightY); #endif if (m_fisheyeVIdeoInfoSEIEnabled) { m_cTEncTop.setFviSEIEnabled(m_fisheyeVideoInfoSEI); } else { m_cTEncTop.setFviSEIDisabled(); } m_cTEncTop.setColourRemapInfoSEIFileRoot ( m_colourRemapSEIFileRoot ); m_cTEncTop.setMasteringDisplaySEI ( m_masteringDisplay ); m_cTEncTop.setSEIAlternativeTransferCharacteristicsSEIEnable ( m_preferredTransferCharacteristics>=0 ); m_cTEncTop.setSEIPreferredTransferCharacteristics ( UChar(m_preferredTransferCharacteristics) ); m_cTEncTop.setSEIGreenMetadataInfoSEIEnable ( m_greenMetadataType > 0 ); m_cTEncTop.setSEIGreenMetadataType ( UChar(m_greenMetadataType) ); m_cTEncTop.setSEIXSDMetricType ( UChar(m_xsdMetricType) ); m_cTEncTop.setRegionalNestingSEIFileRoot ( m_regionalNestingSEIFileRoot ); m_cTEncTop.setAnnotatedRegionSEIFileRoot (m_arSEIFileRoot); m_cTEncTop.setTileUniformSpacingFlag ( m_tileUniformSpacingFlag ); m_cTEncTop.setNumColumnsMinus1 ( m_numTileColumnsMinus1 ); m_cTEncTop.setNumRowsMinus1 ( m_numTileRowsMinus1 ); if(!m_tileUniformSpacingFlag) { m_cTEncTop.setColumnWidth ( m_tileColumnWidth ); m_cTEncTop.setRowHeight ( m_tileRowHeight ); } m_cTEncTop.xCheckGSParameters(); Int uiTilesCount = (m_numTileRowsMinus1+1) * (m_numTileColumnsMinus1+1); if(uiTilesCount == 1) { m_bLFCrossTileBoundaryFlag = true; } m_cTEncTop.setLFCrossTileBoundaryFlag ( m_bLFCrossTileBoundaryFlag ); m_cTEncTop.setEntropyCodingSyncEnabledFlag ( m_entropyCodingSyncEnabledFlag ); m_cTEncTop.setTMVPModeId ( m_TMVPModeId ); m_cTEncTop.setUseScalingListId ( m_useScalingListId ); m_cTEncTop.setScalingListFileName ( m_scalingListFileName ); m_cTEncTop.setSignDataHidingEnabledFlag ( m_signDataHidingEnabledFlag); m_cTEncTop.setUseRateCtrl ( m_RCEnableRateControl ); m_cTEncTop.setTargetBitrate ( m_RCTargetBitrate ); m_cTEncTop.setKeepHierBit ( m_RCKeepHierarchicalBit ); m_cTEncTop.setLCULevelRC ( m_RCLCULevelRC ); m_cTEncTop.setUseLCUSeparateModel ( m_RCUseLCUSeparateModel ); m_cTEncTop.setInitialQP ( m_RCInitialQP ); m_cTEncTop.setForceIntraQP ( m_RCForceIntraQP ); m_cTEncTop.setCpbSaturationEnabled ( m_RCCpbSaturationEnabled ); m_cTEncTop.setCpbSize ( m_RCCpbSize ); m_cTEncTop.setInitialCpbFullness ( m_RCInitialCpbFullness ); m_cTEncTop.setTransquantBypassEnabledFlag ( m_TransquantBypassEnabledFlag ); m_cTEncTop.setCUTransquantBypassFlagForceValue ( m_CUTransquantBypassFlagForce ); m_cTEncTop.setCostMode ( m_costMode ); m_cTEncTop.setUseRecalculateQPAccordingToLambda ( m_recalculateQPAccordingToLambda ); m_cTEncTop.setUseStrongIntraSmoothing ( m_useStrongIntraSmoothing ); m_cTEncTop.setActiveParameterSetsSEIEnabled ( m_activeParameterSetsSEIEnabled ); m_cTEncTop.setVuiParametersPresentFlag ( m_vuiParametersPresentFlag ); m_cTEncTop.setAspectRatioInfoPresentFlag ( m_aspectRatioInfoPresentFlag); m_cTEncTop.setAspectRatioIdc ( m_aspectRatioIdc ); m_cTEncTop.setSarWidth ( m_sarWidth ); m_cTEncTop.setSarHeight ( m_sarHeight ); m_cTEncTop.setOverscanInfoPresentFlag ( m_overscanInfoPresentFlag ); m_cTEncTop.setOverscanAppropriateFlag ( m_overscanAppropriateFlag ); m_cTEncTop.setVideoSignalTypePresentFlag ( m_videoSignalTypePresentFlag ); m_cTEncTop.setVideoFormat ( m_videoFormat ); m_cTEncTop.setVideoFullRangeFlag ( m_videoFullRangeFlag ); m_cTEncTop.setColourDescriptionPresentFlag ( m_colourDescriptionPresentFlag ); m_cTEncTop.setColourPrimaries ( m_colourPrimaries ); m_cTEncTop.setTransferCharacteristics ( m_transferCharacteristics ); m_cTEncTop.setMatrixCoefficients ( m_matrixCoefficients ); m_cTEncTop.setChromaLocInfoPresentFlag ( m_chromaLocInfoPresentFlag ); m_cTEncTop.setChromaSampleLocTypeTopField ( m_chromaSampleLocTypeTopField ); m_cTEncTop.setChromaSampleLocTypeBottomField ( m_chromaSampleLocTypeBottomField ); m_cTEncTop.setNeutralChromaIndicationFlag ( m_neutralChromaIndicationFlag ); m_cTEncTop.setDefaultDisplayWindow ( m_defDispWinLeftOffset, m_defDispWinRightOffset, m_defDispWinTopOffset, m_defDispWinBottomOffset ); m_cTEncTop.setFrameFieldInfoPresentFlag ( m_frameFieldInfoPresentFlag ); m_cTEncTop.setPocProportionalToTimingFlag ( m_pocProportionalToTimingFlag ); m_cTEncTop.setNumTicksPocDiffOneMinus1 ( m_numTicksPocDiffOneMinus1 ); m_cTEncTop.setBitstreamRestrictionFlag ( m_bitstreamRestrictionFlag ); m_cTEncTop.setTilesFixedStructureFlag ( m_tilesFixedStructureFlag ); m_cTEncTop.setMotionVectorsOverPicBoundariesFlag ( m_motionVectorsOverPicBoundariesFlag ); m_cTEncTop.setMinSpatialSegmentationIdc ( m_minSpatialSegmentationIdc ); m_cTEncTop.setMaxBytesPerPicDenom ( m_maxBytesPerPicDenom ); m_cTEncTop.setMaxBitsPerMinCuDenom ( m_maxBitsPerMinCuDenom ); m_cTEncTop.setLog2MaxMvLengthHorizontal ( m_log2MaxMvLengthHorizontal ); m_cTEncTop.setLog2MaxMvLengthVertical ( m_log2MaxMvLengthVertical ); m_cTEncTop.setEfficientFieldIRAPEnabled ( m_bEfficientFieldIRAPEnabled ); m_cTEncTop.setHarmonizeGopFirstFieldCoupleEnabled ( m_bHarmonizeGopFirstFieldCoupleEnabled ); m_cTEncTop.setSummaryOutFilename ( m_summaryOutFilename ); m_cTEncTop.setSummaryPicFilenameBase ( m_summaryPicFilenameBase ); m_cTEncTop.setSummaryVerboseness ( m_summaryVerboseness ); #if JCTVC_AD0021_SEI_MANIFEST m_cTEncTop.setSEIManifestSEIEnabled(m_SEIManifestSEIEnabled); #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION m_cTEncTop.setSEIPrefixIndicationSEIEnabled(m_SEIPrefixIndicationSEIEnabled); #endif } Void TAppEncTop::xCreateLib() { // Video I/O m_cTVideoIOYuvInputFile.open( m_inputFileName, false, m_inputBitDepth, m_MSBExtendedBitDepth, m_internalBitDepth ); // read mode m_cTVideoIOYuvInputFile.skipFrames(m_FrameSkip, m_inputFileWidth, m_inputFileHeight, m_InputChromaFormatIDC); if (!m_reconFileName.empty()) { m_cTVideoIOYuvReconFile.open(m_reconFileName, true, m_outputBitDepth, m_outputBitDepth, m_internalBitDepth); // write mode } #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty()) { m_cTVideoIOYuvSIIPreFile.open(m_shutterIntervalPreFileName, true, m_outputBitDepth, m_outputBitDepth, m_internalBitDepth); // write mode } #endif // Neo Decoder m_cTEncTop.create(); } Void TAppEncTop::xDestroyLib() { // Video I/O m_cTVideoIOYuvInputFile.close(); m_cTVideoIOYuvReconFile.close(); #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty()) { m_cTVideoIOYuvSIIPreFile.close(); } #endif // Neo Decoder m_cTEncTop.destroy(); } Void TAppEncTop::xInitLib(Bool isFieldCoding) { m_cTEncTop.init(isFieldCoding); } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - create internal class - initialize internal variable - until the end of input YUV file, call encoding function in TEncTop class - delete allocated buffers - destroy internal class . */ Void TAppEncTop::encode() { fstream bitstreamFile(m_bitstreamFileName.c_str(), fstream::binary | fstream::out); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for writing\n", m_bitstreamFileName.c_str()); exit(EXIT_FAILURE); } TComPicYuv* pcPicYuvOrg = new TComPicYuv; TComPicYuv* pcPicYuvRec = NULL; #if JVET_X0048_X0103_FILM_GRAIN TComPicYuv* m_filteredOrgPicForFG; if (m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty()) { m_filteredOrgPicForFG = new TComPicYuv; m_filteredOrgPicForFG->create(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true); } else { m_filteredOrgPicForFG = NULL; } #endif // initialize internal class & member variables xInitLibCfg(); xCreateLib(); xInitLib(m_isField); printChromaFormat(); // main encoder loop Int iNumEncoded = 0; Bool bEos = false; const InputColourSpaceConversion ipCSC = m_inputColourSpaceConvert; const InputColourSpaceConversion snrCSC = (!m_snrInternalColourSpace) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED; list outputAccessUnits; ///< list of access units to write out. is populated by the encoding process TComPicYuv cPicYuvTrueOrg; // allocate original YUV buffer if( m_isField ) { pcPicYuvOrg->create ( m_sourceWidth, m_sourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true ); cPicYuvTrueOrg.create(m_sourceWidth, m_sourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true); } else { pcPicYuvOrg->create ( m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true ); cPicYuvTrueOrg.create(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true ); } #if EXTENSION_360_VIDEO TExt360AppEncTop ext360(*this, m_cTEncTop.getGOPEncoder()->getExt360Data(), *(m_cTEncTop.getGOPEncoder()), *pcPicYuvOrg); #endif TEncTemporalFilter temporalFilter; #if JVET_Y0077_BIM if ( m_gopBasedTemporalFilterEnabled || m_bimEnabled ) #else if (m_gopBasedTemporalFilterEnabled) #endif { temporalFilter.init(m_FrameSkip, m_inputBitDepth, m_MSBExtendedBitDepth, m_internalBitDepth, m_sourceWidth, m_sourceHeight, m_sourcePadding, m_framesToBeEncoded, m_bClipInputVideoToRec709Range, m_inputFileName, m_chromaFormatIDC, m_inputColourSpaceConvert, m_iQP, m_iGOPSize, m_gopBasedTemporalFilterStrengths, m_gopBasedTemporalFilterPastRefs, m_gopBasedTemporalFilterFutureRefs, #if !JVET_Y0077_BIM m_firstValidFrame, m_lastValidFrame); #else m_firstValidFrame, m_lastValidFrame, m_gopBasedTemporalFilterEnabled, m_cTEncTop.getAdaptQPmap(), m_bimEnabled); #endif } #if JVET_X0048_X0103_FILM_GRAIN TEncTemporalFilter m_temporalFilterForFG; if ( m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty() ) { int filteredFrame = 0; if ( m_iIntraPeriod < 1 ) filteredFrame = 2 * m_iFrameRate; else filteredFrame = m_iIntraPeriod; map filteredFramesAndStrengths = { { filteredFrame, 1.5 } }; // TODO: adjust MCTF and MCTF strenght m_temporalFilterForFG.init(m_FrameSkip, m_inputBitDepth, m_MSBExtendedBitDepth, m_internalBitDepth, m_sourceWidth, m_sourceHeight, m_sourcePadding, m_framesToBeEncoded, m_bClipInputVideoToRec709Range, m_inputFileName, m_chromaFormatIDC, m_inputColourSpaceConvert, m_iQP, m_iGOPSize, filteredFramesAndStrengths, m_gopBasedTemporalFilterPastRefs, m_gopBasedTemporalFilterFutureRefs, #if !JVET_Y0077_BIM m_firstValidFrame, m_lastValidFrame); #else m_firstValidFrame, m_lastValidFrame, m_gopBasedTemporalFilterEnabled, m_cTEncTop.getAdaptQPmap(), m_bimEnabled); #endif } #endif while ( !bEos ) { // get buffers xGetBuffer(pcPicYuvRec); // read input YUV file #if EXTENSION_360_VIDEO if (ext360.isEnabled()) { ext360.read(m_cTVideoIOYuvInputFile, *pcPicYuvOrg, cPicYuvTrueOrg, ipCSC); } else { m_cTVideoIOYuvInputFile.read( pcPicYuvOrg, &cPicYuvTrueOrg, ipCSC, m_sourcePadding, m_InputChromaFormatIDC, m_bClipInputVideoToRec709Range ); } #else m_cTVideoIOYuvInputFile.read( pcPicYuvOrg, &cPicYuvTrueOrg, ipCSC, m_sourcePadding, m_InputChromaFormatIDC, m_bClipInputVideoToRec709Range ); #endif #if JVET_X0048_X0103_FILM_GRAIN if (m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty()) { pcPicYuvOrg->copyToPic(m_filteredOrgPicForFG); m_temporalFilterForFG.filter(m_filteredOrgPicForFG, m_iFrameRcvd); } #endif #if JVET_Y0077_BIM if ( m_gopBasedTemporalFilterEnabled || m_bimEnabled ) #else if (m_gopBasedTemporalFilterEnabled) #endif { temporalFilter.filter(pcPicYuvOrg, m_iFrameRcvd); } // increase number of received frames m_iFrameRcvd++; bEos = (m_isField && (m_iFrameRcvd == (m_framesToBeEncoded >> 1) )) || ( !m_isField && (m_iFrameRcvd == m_framesToBeEncoded) ); Bool flush = 0; // if end of file (which is only detected on a read failure) flush the encoder of any queued pictures if (m_cTVideoIOYuvInputFile.isEof()) { flush = true; bEos = true; m_iFrameRcvd--; m_cTEncTop.setFramesToBeEncoded(m_iFrameRcvd); } // call encoding function for one frame if ( m_isField ) { m_cTEncTop.encode( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, ipCSC, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded, m_isTopFieldFirst ); } else { #if JVET_X0048_X0103_FILM_GRAIN m_cTEncTop.encode( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, flush ? 0 : m_filteredOrgPicForFG, ipCSC, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded); #else m_cTEncTop.encode( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, ipCSC, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded ); #endif } #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_ShutterFilterEnable && !m_shutterIntervalPreFileName.empty()) { m_cTVideoIOYuvSIIPreFile.write(pcPicYuvOrg, ipCSC, m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range); } #endif // write bistream to file if necessary if ( iNumEncoded > 0 ) { xWriteOutput(bitstreamFile, iNumEncoded, outputAccessUnits); outputAccessUnits.clear(); } // temporally skip frames if( m_temporalSubsampleRatio > 1 ) { m_cTVideoIOYuvInputFile.skipFrames(m_temporalSubsampleRatio-1, m_inputFileWidth, m_inputFileHeight, m_InputChromaFormatIDC); } } m_cTEncTop.printSummary(m_isField); // delete original YUV buffer pcPicYuvOrg->destroy(); delete pcPicYuvOrg; pcPicYuvOrg = NULL; #if JVET_X0048_X0103_FILM_GRAIN if (m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty()) { m_filteredOrgPicForFG->destroy(); delete m_filteredOrgPicForFG; m_filteredOrgPicForFG = NULL; } #endif // delete used buffers in encoder class m_cTEncTop.deletePicBuffer(); cPicYuvTrueOrg.destroy(); // delete buffers & classes xDeleteBuffer(); xDestroyLib(); printRateSummary(); return; } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== /** - application has picture buffer list with size of GOP - picture buffer list acts as ring buffer - end of the list has the latest picture . */ Void TAppEncTop::xGetBuffer( TComPicYuv*& rpcPicYuvRec) { assert( m_iGOPSize > 0 ); // org. buffer if ( m_cListPicYuvRec.size() >= (UInt)m_iGOPSize ) // buffer will be 1 element longer when using field coding, to maintain first field whilst processing second. { rpcPicYuvRec = m_cListPicYuvRec.popFront(); } else { rpcPicYuvRec = new TComPicYuv; rpcPicYuvRec->create( m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxTotalCUDepth, true ); } m_cListPicYuvRec.pushBack( rpcPicYuvRec ); } Void TAppEncTop::xDeleteBuffer( ) { TComList::iterator iterPicYuvRec = m_cListPicYuvRec.begin(); Int iSize = Int( m_cListPicYuvRec.size() ); for ( Int i = 0; i < iSize; i++ ) { TComPicYuv* pcPicYuvRec = *(iterPicYuvRec++); pcPicYuvRec->destroy(); delete pcPicYuvRec; pcPicYuvRec = NULL; } } /** Write access units to output file. \param bitstreamFile target bitstream file \param iNumEncoded number of encoded frames \param accessUnits list of access units to be written */ Void TAppEncTop::xWriteOutput(std::ostream& bitstreamFile, Int iNumEncoded, const std::list& accessUnits) { const InputColourSpaceConversion ipCSC = (!m_outputInternalColourSpace) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED; if (m_isField) { //Reinterlace fields Int i; TComList::iterator iterPicYuvRec = m_cListPicYuvRec.end(); list::const_iterator iterBitstream = accessUnits.begin(); for ( i = 0; i < iNumEncoded; i++ ) { --iterPicYuvRec; } for ( i = 0; i < iNumEncoded/2; i++ ) { TComPicYuv* pcPicYuvRecTop = *(iterPicYuvRec++); TComPicYuv* pcPicYuvRecBottom = *(iterPicYuvRec++); if (!m_reconFileName.empty()) { m_cTVideoIOYuvReconFile.write( pcPicYuvRecTop, pcPicYuvRecBottom, ipCSC, m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom, NUM_CHROMA_FORMAT, m_isTopFieldFirst ); } const AccessUnit& auTop = *(iterBitstream++); const vector& statsTop = writeAnnexB(bitstreamFile, auTop); rateStatsAccum(auTop, statsTop); const AccessUnit& auBottom = *(iterBitstream++); const vector& statsBottom = writeAnnexB(bitstreamFile, auBottom); rateStatsAccum(auBottom, statsBottom); } } else { Int i; TComList::iterator iterPicYuvRec = m_cListPicYuvRec.end(); list::const_iterator iterBitstream = accessUnits.begin(); for ( i = 0; i < iNumEncoded; i++ ) { --iterPicYuvRec; } for ( i = 0; i < iNumEncoded; i++ ) { TComPicYuv* pcPicYuvRec = *(iterPicYuvRec++); if (!m_reconFileName.empty()) { m_cTVideoIOYuvReconFile.write( pcPicYuvRec, ipCSC, m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range ); } const AccessUnit& au = *(iterBitstream++); const vector& stats = writeAnnexB(bitstreamFile, au); rateStatsAccum(au, stats); } } } /** * */ Void TAppEncTop::rateStatsAccum(const AccessUnit& au, const std::vector& annexBsizes) { AccessUnit::const_iterator it_au = au.begin(); vector::const_iterator it_stats = annexBsizes.begin(); for (; it_au != au.end(); it_au++, it_stats++) { switch ((*it_au)->m_nalUnitType) { case NAL_UNIT_CODED_SLICE_TRAIL_R: case NAL_UNIT_CODED_SLICE_TRAIL_N: case NAL_UNIT_CODED_SLICE_TSA_R: case NAL_UNIT_CODED_SLICE_TSA_N: case NAL_UNIT_CODED_SLICE_STSA_R: case NAL_UNIT_CODED_SLICE_STSA_N: case NAL_UNIT_CODED_SLICE_BLA_W_LP: case NAL_UNIT_CODED_SLICE_BLA_W_RADL: case NAL_UNIT_CODED_SLICE_BLA_N_LP: case NAL_UNIT_CODED_SLICE_IDR_W_RADL: case NAL_UNIT_CODED_SLICE_IDR_N_LP: case NAL_UNIT_CODED_SLICE_CRA: case NAL_UNIT_CODED_SLICE_RADL_N: case NAL_UNIT_CODED_SLICE_RADL_R: case NAL_UNIT_CODED_SLICE_RASL_N: case NAL_UNIT_CODED_SLICE_RASL_R: case NAL_UNIT_VPS: case NAL_UNIT_SPS: case NAL_UNIT_PPS: m_essentialBytes += *it_stats; break; default: break; } m_totalBytes += *it_stats; } } Void TAppEncTop::printRateSummary() { Double time = (Double) m_iFrameRcvd / m_iFrameRate * m_temporalSubsampleRatio; printf("Bytes written to file: %u (%.3f kbps)\n", m_totalBytes, 0.008 * m_totalBytes / time); if (m_summaryVerboseness > 0) { printf("Bytes for SPS/PPS/Slice (Incl. Annex B): %u (%.3f kbps)\n", m_essentialBytes, 0.008 * m_essentialBytes / time); } } Void TAppEncTop::printChromaFormat() { std::cout << std::setw(43) << "Input ChromaFormatIDC = "; switch (m_InputChromaFormatIDC) { case CHROMA_400: std::cout << " 4:0:0"; break; case CHROMA_420: std::cout << " 4:2:0"; break; case CHROMA_422: std::cout << " 4:2:2"; break; case CHROMA_444: std::cout << " 4:4:4"; break; default: std::cerr << "Invalid"; exit(1); } std::cout << std::endl; std::cout << std::setw(43) << "Output (internal) ChromaFormatIDC = "; switch (m_cTEncTop.getChromaFormatIdc()) { case CHROMA_400: std::cout << " 4:0:0"; break; case CHROMA_420: std::cout << " 4:2:0"; break; case CHROMA_422: std::cout << " 4:2:2"; break; case CHROMA_444: std::cout << " 4:4:4"; break; default: std::cerr << "Invalid"; exit(1); } std::cout << "\n" << std::endl; } //! \} HM-HM-18.0/source/App/TAppEncoder/TAppEncTop.h000066400000000000000000000102661442026013100205600ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppEncTop.h \brief Encoder application class (header) */ #ifndef __TAPPENCTOP__ #define __TAPPENCTOP__ #include #include #include "TLibEncoder/TEncTop.h" #include "Utilities/TVideoIOYuv.h" #include "TLibCommon/AccessUnit.h" #include "TAppEncCfg.h" //! \ingroup TAppEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// encoder application class class TAppEncTop : public TAppEncCfg { private: // class interface TEncTop m_cTEncTop; ///< encoder class TVideoIOYuv m_cTVideoIOYuvInputFile; ///< input YUV file TVideoIOYuv m_cTVideoIOYuvReconFile; ///< output reconstruction file #if SHUTTER_INTERVAL_SEI_PROCESSING TVideoIOYuv m_cTVideoIOYuvSIIPreFile; ///< output pre-filtered file #endif TComList m_cListPicYuvRec; ///< list of reconstruction YUV files Int m_iFrameRcvd; ///< number of received frames UInt m_essentialBytes; UInt m_totalBytes; protected: // initialization Void xCreateLib (); ///< create files & encoder class Void xInitLibCfg (); ///< initialize internal variables Void xInitLib (Bool isFieldCoding); ///< initialize encoder class Void xDestroyLib (); ///< destroy encoder class /// obtain required buffers Void xGetBuffer(TComPicYuv*& rpcPicYuvRec); /// delete allocated buffers Void xDeleteBuffer (); // file I/O Void xWriteOutput(std::ostream& bitstreamFile, Int iNumEncoded, const std::list& accessUnits); ///< write bitstream to file Void rateStatsAccum(const AccessUnit& au, const std::vector& stats); Void printRateSummary(); Void printChromaFormat(); public: TAppEncTop(); virtual ~TAppEncTop(); Void encode (); ///< main encoding function TEncTop& getTEncTop () { return m_cTEncTop; } ///< return encoder class pointer reference };// END CLASS DEFINITION TAppEncTop //! \} #endif // __TAPPENCTOP__ HM-HM-18.0/source/App/TAppEncoder/encmain.cpp000066400000000000000000000070101442026013100205410ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file encmain.cpp \brief Encoder application main */ #include #include #include "TAppEncTop.h" #include "Utilities/program_options_lite.h" //! \ingroup TAppEncoder //! \{ #include "../Lib/TLibCommon/Debug.h" // ==================================================================================================================== // Main function // ==================================================================================================================== int main(int argc, char* argv[]) { TAppEncTop cTAppEncTop; // print information fprintf( stdout, "\n" ); fprintf( stdout, "HM software: Encoder Version [%s] (including RExt)", NV_VERSION ); fprintf( stdout, NVM_ONOS ); fprintf( stdout, NVM_COMPILEDBY ); fprintf( stdout, NVM_BITS ); fprintf( stdout, "\n\n" ); // create application encoder class cTAppEncTop.create(); // parse configuration try { if(!cTAppEncTop.parseCfg( argc, argv )) { cTAppEncTop.destroy(); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST EnvVar::printEnvVar(); #endif return 1; } } catch (df::program_options_lite::ParseFailure &e) { std::cerr << "Error parsing option \""<< e.arg <<"\" with argument \""<< e.val <<"\"." << std::endl; return 1; } #if PRINT_MACRO_VALUES printMacroSettings(); #endif #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST EnvVar::printEnvVarInUse(); #endif // starting time Double dResult; clock_t lBefore = clock(); // call encoding function cTAppEncTop.encode(); // ending time dResult = (Double)(clock()-lBefore) / CLOCKS_PER_SEC; printf("\n Total Time: %12.3f sec.\n", dResult); // destroy application encoder class cTAppEncTop.destroy(); return 0; } //! \} HM-HM-18.0/source/App/TAppMCTSExtractor/000077500000000000000000000000001442026013100175105ustar00rootroot00000000000000HM-HM-18.0/source/App/TAppMCTSExtractor/CMakeLists.txt000066400000000000000000000052421442026013100222530ustar00rootroot00000000000000# executable set( EXE_NAME MCTSExtractor ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # get additional libs for gcc on Ubuntu systems if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) if( USE_ADDRESS_SANITIZER ) set( ADDITIONAL_LIBS asan ) endif() endif() endif() # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # add executable add_executable( ${EXE_NAME} ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) if( HIGH_BITDEPTH ) target_compile_definitions( ${EXE_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() if( CMAKE_COMPILER_IS_GNUCC AND BUILD_STATIC ) set( ADDITIONAL_LIBS ${ADDITIONAL_LIBS} -static -static-libgcc -static-libstdc++ ) target_compile_definitions( ${EXE_NAME} PUBLIC ENABLE_WPP_STATIC_LINK=1 ) endif() target_link_libraries( ${EXE_NAME} TLibCommon TLibEncoder TLibDecoder Utilities Threads::Threads ${ADDITIONAL_LIBS} ) if( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) add_custom_command( TARGET ${EXE_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/MCTSExtractor> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/MCTSExtractor> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO}/MCTSExtractor> $<$:${CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL}/MCTSExtractor> $<$:${CMAKE_SOURCE_DIR}/bin/MCTSExtractorStaticd> $<$:${CMAKE_SOURCE_DIR}/bin/MCTSExtractorStatic> $<$:${CMAKE_SOURCE_DIR}/bin/MCTSExtractorStaticp> $<$:${CMAKE_SOURCE_DIR}/bin/MCTSExtractorStaticm> ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${EXE_NAME} PROPERTIES FOLDER app LINKER_LANGUAGE CXX ) HM-HM-18.0/source/App/TAppMCTSExtractor/TAppMctsExtCfg.cpp000066400000000000000000000070511442026013100230130ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppMctsExtCfg.cpp \brief MCTS Extractor configuration class */ #include #include #include #include "TAppMctsExtCfg.h" #include "Utilities/program_options_lite.h" #ifdef WIN32 #define strdup _strdup #endif using namespace std; namespace po = df::program_options_lite; #if MCTS_EXTRACTION //! \ingroup TAppMctsExtract //! \{ // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param argc number of arguments \param argv array of arguments */ Bool TAppMctsExtCfg::parseCfg(Int argc, TChar* argv[]) { Bool do_help = false; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("c", po::parseConfigFile, "configuration file name") ("InputBitstreamFile,i", m_inputBitstreamFileName, string(""), "Input bitstream file name") ("OutputBitstreamFile,b", m_outputBitstreamFileName, string(""), "Output subbitstream file name") ("TargetMCTSIdx,d", m_targetMctsIdx, 0, "Target MCTS idx to be extracted. TargetMCTSIdx = 0 per default.") ; po::setDefaults(opts); po::ErrorReporter err; const list& argv_unhandled = po::scanArgv(opts, argc, (const TChar**)argv, err); for (list::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { fprintf(stderr, "Unhandled argument ignored: `%s'\n", *it); } if (argc == 1 || do_help) { po::doHelp(cout, opts); return false; } if (m_inputBitstreamFileName.empty()) { fprintf(stderr, "No input file specified, aborting\n"); return false; } return true; } #endif //! \} HM-HM-18.0/source/App/TAppMCTSExtractor/TAppMctsExtCfg.h000066400000000000000000000056461442026013100224700ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppMmctsExtCfg.h \brief MCTS Extractor configuration class (header) */ #ifndef __TAPPMCTSEXTCFG__ #define __TAPPMCTSEXTCFG__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include #if MCTS_EXTRACTION //! \ingroup TAppMctsExt //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// MCTS Extraction configuration class class TAppMctsExtCfg { protected: std::string m_inputBitstreamFileName; ///< input bitstream file name std::string m_outputBitstreamFileName; ///< output subbitstream filename Int m_targetMctsIdx; ///< MCTS Id extracted public: TAppMctsExtCfg() : m_inputBitstreamFileName() , m_outputBitstreamFileName() , m_targetMctsIdx(-1) { } virtual ~TAppMctsExtCfg() {} Bool parseCfg(Int argc, TChar* argv[]); ///< initialize option class from configuration }; //! \} #endif #endif HM-HM-18.0/source/App/TAppMCTSExtractor/TAppMctsExtTop.cpp000066400000000000000000000351571442026013100230660ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppMctsExtTop.cpp \brief MCTS Extractor application class */ #include #include #include #include #include #include #include "TAppMctsExtTop.h" #include "TLibDecoder/AnnexBread.h" #include "TLibDecoder/NALread.h" #include "TLibEncoder/NALwrite.h" #include "TLibCommon/SEI.h" #if MCTS_EXTRACTION //! \ingroup TAppMctsExt //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== TAppMctsExtTop::TAppMctsExtTop() { } Void TAppMctsExtTop::create() { m_mctsExtractionInfoPresent = false; } Void TAppMctsExtTop::destroy() { m_inputBitstreamFileName.clear(); m_outputBitstreamFileName.clear(); } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - create internal class - initialize internal class - until the end of the bitstream, call extraction function in TDecMctsExt class - delete allocated buffers - destroy internal class . */ Void TAppMctsExtTop::extract() { ifstream bitstreamFile(m_inputBitstreamFileName.c_str(), ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open input bitstream file `%s' for reading\n", m_inputBitstreamFileName.c_str()); exit(EXIT_FAILURE); } InputByteStream bytestream(bitstreamFile); // create & initialize internal classes xCreateMctsExtLib(); xInitMctsExtLib(); Int iSkipFrame = 0; Int iPOCLastDisplay = 0; fstream bitstreamFileOut(m_outputBitstreamFileName.c_str(), fstream::binary | fstream::out); if (!bitstreamFileOut) { fprintf(stderr, "\nfailed to open output bitstream file `%s' for writing\n", m_outputBitstreamFileName.c_str()); exit(EXIT_FAILURE); } AccessUnit outAccessUnit; while (!!bitstreamFile) { streampos location = bitstreamFile.tellg(); AnnexBStats stats = AnnexBStats(); InputNALUnit inNalu; byteStreamNALUnit(bytestream, inNalu.getBitstream().getFifo(), stats); Bool bNewPicture = false; if (inNalu.getBitstream().getFifo().empty()) { fprintf(stderr, "Warning: Attempt to extract an empty NAL unit\n"); } else { read(inNalu); m_pcSlice = m_cTDecTop.getApcSlicePilot(); // decode HLS, skipping cabac decoding and reconstruction bNewPicture = m_cTDecTop.decode(inNalu, iSkipFrame, iPOCLastDisplay, true); if (bNewPicture) { bitstreamFile.clear(); bitstreamFile.seekg(location - streamoff(3)); bytestream.reset(); } } if ((bNewPicture || !bitstreamFile || inNalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cTDecTop.getFirstSliceInSequence()) { m_cTDecTop.getPcPic()->setReconMark(true); if (bitstreamFile || inNalu.m_nalUnitType == NAL_UNIT_EOS) { m_cTDecTop.setFirstSliceInPicture(true); } } if ((inNalu.m_nalUnitType == NAL_UNIT_VPS || inNalu.m_nalUnitType == NAL_UNIT_SPS || inNalu.m_nalUnitType == NAL_UNIT_PPS)) { continue; } else if (!m_mctsExtractionInfoPresent && inNalu.isSei()) { // search matching EIS and push parameter sets into AU m_cTDecTop.xParsePrefixSEImessages(); if (!m_cTDecTop.getSEIs().empty()) { xExtractSuitableParameterSets( getSeisByType(m_cTDecTop.getSEIs(), SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS), getSeisByType(m_cTDecTop.getSEIs(), SEI::MCTS_EXTRACTION_INFO_SET), outAccessUnit); } } else if (!bNewPicture && m_mctsExtractionInfoPresent && inNalu.isSlice() && xIsNaluWithinMCTSSet(m_targetMctsIdx)) { //rewrite input slice // setup UInt numCtusInOutputPictures = m_cTDecTop.getPcPic()->getPicSym()->getTComTile(m_targetMctsIdx)->getTileHeightInCtus() * m_cTDecTop.getPcPic()->getPicSym()->getTComTile(m_targetMctsIdx)->getTileWidthInCtus(); UInt numCtusInInputPictures = m_cTDecTop.getPcPic()->getNumberOfCtusInFrame(); m_cSlicePicSym.setNumberOfCtusInFrame(m_cTDecTop.getPcPic()->getPicSym(), numCtusInOutputPictures); m_pcSlice->setPic(m_cTDecTop.getPcPic()); m_pcSlice->setSliceSegmentCurStartCtuTsAddr(0); OutputNALUnit outNalu(m_pcSlice->getNalUnitType(), m_pcSlice->getTLayer()); m_cEntropyCoder.setEntropyCoder(&m_cCavlcCoder); m_cEntropyCoder.setBitstream(&outNalu.m_Bitstream); m_cEntropyCoder.encodeSliceHeader(m_pcSlice); //convert xInputToOutputSliceNaluConversion(inNalu, outNalu, m_pcSlice); //write to file outAccessUnit.push_back(new NALUnitEBSP(outNalu)); xWriteOutput(bitstreamFileOut, outAccessUnit); outAccessUnit.clear(); //m_cTDecTop.getPcPic()->setNumberOfCtusInFrame(numCtusInInputPictures); m_cSlicePicSym.setNumberOfCtusInFrame(m_cTDecTop.getPcPic()->getPicSym(), numCtusInInputPictures); // console output TChar c = (m_pcSlice->isIntra() ? 'I' : m_pcSlice->isInterP() ? 'P' : 'B'); if (!m_pcSlice->isReferenced()) { c += 32; } printf("POC %4d TId: %1d ( %c-SLICE, QP%3d ) ", m_pcSlice->getPOC(), m_pcSlice->getTLayer(), c, m_pcSlice->getSliceQp()); printf(" %10d bits\n", (int)inNalu.getBitstream().getFifo().size()); } } if (!m_mctsExtractionInfoPresent) { fprintf(stderr, "\nInput bitstream file `%s' does not contain MCTS extraction information for target MCTS index %d\n", m_inputBitstreamFileName.c_str(), m_targetMctsIdx); } // delete buffers m_cTDecTop.deletePicBuffer(); // destroy internal classes xDestroyMctsExtLib(); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Void TAppMctsExtTop::xCreateMctsExtLib() { // create decoder class m_cTDecTop.create(); } Void TAppMctsExtTop::xDestroyMctsExtLib() { // destroy decoder class m_cTDecTop.destroy(); } Void TAppMctsExtTop::xInitMctsExtLib() { // initialize decoder class m_cTDecTop.init(); } Void TAppMctsExtTop::xExtractSuitableParameterSets(SEIMessages SEIMctsSEIs, SEIMessages SEIMctsEisSEIs, AccessUnit &accessUnit) { if (SEIMctsSEIs.size() && SEIMctsEisSEIs.size()) { SEIMCTSExtractionInfoSet* SEIMCTSExtractionInfoSetSEI = (SEIMCTSExtractionInfoSet*) *(SEIMctsEisSEIs.begin()); for (std::vector::iterator EisIter = SEIMCTSExtractionInfoSetSEI->m_MCTSExtractionInfoSets.begin(); EisIter != SEIMCTSExtractionInfoSetSEI->m_MCTSExtractionInfoSets.end(); EisIter++) { for (int j = 0; j < EisIter->m_idxOfMctsInSet.size() && !m_mctsExtractionInfoPresent; j++) { for (int k = 0; k < EisIter->m_idxOfMctsInSet[j].size() && !m_mctsExtractionInfoPresent; k++) { if (EisIter->m_idxOfMctsInSet[j][k] == m_targetMctsIdx) { std::vector vps_rbsps; vps_rbsps.resize(EisIter->m_vpsRbspData.size()); for (int jj = 0; jj < EisIter->m_vpsRbspData.size(); jj++) { for (int kk = 0; kk < EisIter->m_vpsRbspDataLength[jj]; kk++) { vps_rbsps[jj].getFifo().push_back(EisIter->m_vpsRbspData[jj][kk]); } OutputNALUnit vpsout(NAL_UNIT_VPS, 0, 0); vpsout.m_Bitstream.getFIFO() = vps_rbsps[jj].getFifo(); accessUnit.push_back(new NALUnitEBSP(vpsout)); } std::vector sps_rbsps; sps_rbsps.resize(EisIter->m_spsRbspData.size()); for (int jj = 0; jj < EisIter->m_spsRbspData.size(); jj++) { for (int kk = 0; kk < EisIter->m_spsRbspDataLength[jj]; kk++) { sps_rbsps[jj].getFifo().push_back(EisIter->m_spsRbspData[jj][kk]); } OutputNALUnit spsout(NAL_UNIT_SPS, 0, 0); spsout.m_Bitstream.getFIFO() = sps_rbsps[jj].getFifo(); accessUnit.push_back(new NALUnitEBSP(spsout)); } std::vector pps_rbsps; pps_rbsps.resize(EisIter->m_ppsRbspData.size()); for (int jj = 0; jj < EisIter->m_ppsRbspData.size(); jj++) { for (int kk = 0; kk < EisIter->m_ppsRbspDataLength[jj]; kk++) { pps_rbsps[jj].getFifo().push_back(EisIter->m_ppsRbspData[jj][kk]); } OutputNALUnit ppsout(NAL_UNIT_PPS, 0, 0); ppsout.m_Bitstream.getFIFO() = pps_rbsps[jj].getFifo(); accessUnit.push_back(new NALUnitEBSP(ppsout)); } TComSPS* nestedSps = new TComSPS(); m_cEntropyDecoder.setEntropyDecoder(&m_cCavlcDecoder); m_cEntropyDecoder.setBitstream(&sps_rbsps[0]); m_cEntropyDecoder.decodeSPS(nestedSps); printf("MCTS extraction info for target MCTS index %d found\n", m_targetMctsIdx); printf("Output bitstream resolution: %dx%d\n\n", nestedSps->getPicWidthInLumaSamples(), nestedSps->getPicHeightInLumaSamples()); m_mctsExtractionInfoPresent = true; } } } } } } Bool TAppMctsExtTop::xIsNaluWithinMCTSSet(Int mcts_id) { UInt currNaluTSSliceSegAddr = m_pcSlice->getSliceSegmentCurStartCtuTsAddr(); UInt firstCtuAddrTSInMcts = m_cTDecTop.getPcPic()->getPicSym()->getCtuRsToTsAddrMap(m_cTDecTop.getPcPic()->getPicSym()->getTComTile(m_targetMctsIdx)->getFirstCtuRsAddr()); UInt lastCtuAddrTSInMcts = -1; if (mcts_id < (m_cTDecTop.getPcPic()->getPicSym()->getNumTiles() - 1)) {// not last tile lastCtuAddrTSInMcts = m_cTDecTop.getPcPic()->getPicSym()->getCtuRsToTsAddrMap(m_cTDecTop.getPcPic()->getPicSym()->getTComTile(m_targetMctsIdx + 1)->getFirstCtuRsAddr()) - 1; } else { lastCtuAddrTSInMcts = m_cTDecTop.getPcPic()->getNumberOfCtusInFrame() - 1; } return (currNaluTSSliceSegAddr >= firstCtuAddrTSInMcts && currNaluTSSliceSegAddr <= lastCtuAddrTSInMcts); } Void TAppMctsExtTop::xInputToOutputSliceNaluConversion(InputNALUnit &inNalu, OutputNALUnit &outNalu, TComSlice* curSlice) { const UInt uiNumSubstreams = curSlice->getNumberOfSubstreamSizes() + 1; TComInputBitstream **ppcSubstreams = NULL; ppcSubstreams = new TComInputBitstream*[uiNumSubstreams]; for (UInt ui = 0; ui < uiNumSubstreams; ui++) { ppcSubstreams[ui] = inNalu.getBitstream().extractSubstream(ui + 1 < uiNumSubstreams ? (curSlice->getSubstreamSize(ui) << 3) : inNalu.getBitstream().getNumBitsLeft()); } TComOutputBitstream *pcBitstreamRedirect; pcBitstreamRedirect = new TComOutputBitstream; // Append substreams... TComOutputBitstream *pcOut = pcBitstreamRedirect; std::vector substreamsOut(uiNumSubstreams); for (UInt ui = 0; ui < uiNumSubstreams; ui++) { std::vector &bufIn = ppcSubstreams[ui]->getFifo(); std::vector &bufOut = substreamsOut[ui].getFIFO(); bufOut.resize(bufIn.size()); bufOut = bufIn; pcOut->addSubstream(&(substreamsOut[ui])); } // Byte-align outNalu.m_Bitstream.writeByteAlignment(); // Perform bitstream concatenation if (pcOut->getNumberOfWrittenBits() > 0) { outNalu.m_Bitstream.addSubstream(pcOut); } // clean-up for (UInt ui = 0; ui < uiNumSubstreams; ui++) { delete ppcSubstreams[ui]; } delete[] ppcSubstreams; delete pcBitstreamRedirect; return; } Void TAppMctsExtTop::xWriteOutput(std::ostream& bitstreamFile, const AccessUnit accessUnit) { for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++) { const NALUnitEBSP& nalu = **it; static const UChar start_code_prefix[] = { 0,0,0,1 }; if (it == accessUnit.begin() || nalu.m_nalUnitType == NAL_UNIT_VPS || nalu.m_nalUnitType == NAL_UNIT_SPS || nalu.m_nalUnitType == NAL_UNIT_PPS) { /* From AVC, When any of the following conditions are fulfilled, the * zero_byte syntax element shall be present: * - the nal_unit_type within the nal_unit() is equal to 7 (sequence * parameter set) or 8 (picture parameter set), * - the byte stream NAL unit syntax structure contains the first NAL * unit of an access unit in decoding order, as specified by subclause * 7.4.1.2.3. */ bitstreamFile.write(reinterpret_cast(start_code_prefix), 4); } else { bitstreamFile.write(reinterpret_cast(start_code_prefix + 1), 3); } bitstreamFile << nalu.m_nalUnitData.str(); } } #endif HM-HM-18.0/source/App/TAppMCTSExtractor/TAppMctsExtTop.h000066400000000000000000000103471442026013100225250ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TAppMctsExtTop.h \brief MCTS Extractor application class (header) */ #ifndef __TAPPMCTSEXTTOP__ #define __TAPPMCTSEXTTOP__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibDecoder/TDecTop.h" #include "TLibEncoder/TEncTop.h" #include "TLibCommon/AccessUnit.h" #if MCTS_EXTRACTION #include "TAppMctsExtCfg.h" //! \ingroup TAppMctsExt //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// MCTS Extraction application class class TAppMctsExtTop : public TAppMctsExtCfg { private: // class interface TDecTop m_cTDecTop; ///< decoder class TComSlice* m_pcSlice; ///< slice header class TDecEntropy m_cEntropyDecoder; ///< entropy decoder class TDecCavlc m_cCavlcDecoder; ///< CAVLC decoder class TEncEntropy m_cEntropyCoder; ///< entropy encoder class TEncCavlc m_cCavlcCoder; ///< CAVLC encoder class MctsExtractorTComPicSym m_cSlicePicSym; Bool m_mctsExtractionInfoPresent; ///< indicates whether MCTS extraction info for the traget mcts idx has been found in the bitstream public: TAppMctsExtTop(); virtual ~TAppMctsExtTop() {}; Void create(); ///< create internal members Void destroy(); ///< destroy internal members Void extract(); ///< main extracting function protected: Void xCreateMctsExtLib(); ///< create internal classes Void xDestroyMctsExtLib(); ///< destroy internal classes Void xInitMctsExtLib(); ///< initialize decoder class Void xExtractSuitableParameterSets(SEIMessages SEIMctsSEIs, SEIMessages SEIMctsEisSEIs, AccessUnit &accessUnit); ///< search suitable EIS and extract parameter sets into AU Bool xIsNaluWithinMCTSSet(Int MCTS_id); ///< check whether given Nalu belongs to MCTS SET Void xInputToOutputSliceNaluConversion(InputNALUnit &inNalu, OutputNALUnit &outNalu, TComSlice* curSlice); ///< input to output nalu conversion Void xWriteOutput(std::ostream& bitstreamFile, const AccessUnit accessUnit); ///< write AU into output bitstream }; //! \} #endif #endif HM-HM-18.0/source/App/TAppMCTSExtractor/mctsExtmain.cpp000066400000000000000000000063101442026013100225100ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file mctsExtmain.cpp \brief MCTS extractor application main */ #include #include #include #include "TAppMctsExtTop.h" //! \ingroup TAppMctsExt //! \{ // ==================================================================================================================== // Main function // ==================================================================================================================== int main(int argc, char* argv[]) { Int returnCode = EXIT_SUCCESS; #if MCTS_EXTRACTION TAppMctsExtTop cTAppMctsExtTop; // print information fprintf(stdout, "\n"); fprintf(stdout, "HM software: MCTS Extractor Version [%s] ", NV_VERSION); fprintf(stdout, NVM_ONOS); fprintf(stdout, NVM_COMPILEDBY); fprintf(stdout, NVM_BITS); fprintf(stdout, "\n"); // create application MCTS Extraction class cTAppMctsExtTop.create(); // parse configuration if (!cTAppMctsExtTop.parseCfg(argc, argv)) { cTAppMctsExtTop.destroy(); returnCode = EXIT_FAILURE; return returnCode; } // starting time Double dResult; clock_t lBefore = clock(); // call extraction function cTAppMctsExtTop.extract(); // ending time dResult = (Double)(clock() - lBefore) / CLOCKS_PER_SEC; printf("\n Total Time: %12.3f sec.\n", dResult); // destroy application extractor class cTAppMctsExtTop.destroy(); #endif return returnCode; } //! \} HM-HM-18.0/source/App/utils/000077500000000000000000000000001442026013100154215ustar00rootroot00000000000000HM-HM-18.0/source/App/utils/BitrateTargeting/000077500000000000000000000000001442026013100206605ustar00rootroot00000000000000HM-HM-18.0/source/App/utils/BitrateTargeting/ExtractBitrates.cpp000066400000000000000000000147741442026013100245110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "ExtractBitrates.h" #include #include #include #include #include namespace { /// Maintains a sum and a sample-count for calculating averages class Tally { public: /// Contructs a new zeroed tally Tally( ): m_sum( 0.0 ), m_numSlices( 0 ) { } /// Adds to the sum and increments the sample-count void add( double in ) { ++m_numSlices; m_sum += in; } /// \return The calculated average double average( ) const { return m_sum / ( double )m_numSlices; } private: double m_sum; unsigned long m_numSlices; }; /// Ignores all of the the characters up to and including a given character /// \param line The line being read from /// \param iLine The active input stream /// \param character The character to ignore up to /// \throw POCParseException if the stream goes bad before character is encountered or just after character is encountered void ignoreUpTo( const std::string& line, std::istream& iLine, char character ) { while( iLine.good( ) && character != iLine.get( ) ) ; if( !iLine.good( ) ) { throw POCParseException( line ); } } /// Extracts the average bitrates for each of the temporal layers from the given log /// \param i The input stream that represents the log /// \return A map that countains the average bitrates for each temporal layer. Each pair contains the QP value in first and the average bitrate in second. /// \throw POCParseException if an error occured while parsing a POC line std::map< unsigned char, double > extractBitratesForQPs( std::istream& i ) { std::map< unsigned char, Tally > tallyMap; while( i.good( ) ) { // Initialize variables for this line std::string line; std::getline( i, line ); std::istringstream iLine( line ); if( !iLine.good( ) ) { continue; } // Ignore the "POC" if( iLine.get( ) != 'P' ) { continue; } if( !iLine.good( ) ) { continue; } if( iLine.get( ) != 'O' ) { continue; } if( !iLine.good( ) ) { continue; } if( iLine.get( ) != 'C' ) { continue; } if( !iLine.good( ) ) { throw POCParseException( line ); } ignoreUpTo( line, iLine, '(' ); if( iLine.get( ) != ' ' ) { throw POCParseException( line ); } if( !iLine.good( ) ) { throw POCParseException( line ); } if( 'I' == iLine.get( ) ) { continue; } if( !iLine.good( ) ) { throw POCParseException( line ); } ignoreUpTo( line, iLine, ' ' ); ignoreUpTo( line, iLine, ' ' ); // Parse the qpIndex long qpIndexLong; iLine >> qpIndexLong; if( ( long )std::numeric_limits< unsigned char >::max( ) < qpIndexLong ) { throw POCParseException( line ); } unsigned char qpIndex( ( unsigned char )qpIndexLong ); if( !iLine.good( ) ) { throw POCParseException( line ); } ignoreUpTo( line, iLine, ')' ); ignoreUpTo( line, iLine, ' ' ); // Parse the number of bits unsigned long bitsULong; iLine >> bitsULong; if( !iLine.good( ) ) { throw POCParseException( line ); } // Find the tally that corresponds to our QP. If there is no such tally yet, then add a new one to the map. std::map< unsigned char, Tally >::iterator iter( tallyMap.find( qpIndex ) ); if( tallyMap.end( ) == iter ) { tallyMap[ qpIndex ] = Tally( ); iter = tallyMap.find( qpIndex ); } assert( iter != tallyMap.end( ) ); iter->second.add( ( double )bitsULong ); } // Populate and return the result based on all of the tallies std::map< unsigned char, double > result; for( std::map< unsigned char, Tally >::const_iterator iter( tallyMap.begin( ) ); iter != tallyMap.end( ); ++iter ) { result[ iter->first ] = iter->second.average( ); } return result; } } std::vector< double > extractBitratesForTemporalLayers( std::istream& i ) { std::vector< double > result; std::map< unsigned char, double > bitratesForQPsMap( extractBitratesForQPs( i ) ); if( !bitratesForQPsMap.empty( ) ) { unsigned char expectedNextQPIndex( bitratesForQPsMap.begin( )->first ); for( std::map< unsigned char, double >::const_iterator i( bitratesForQPsMap.begin( ) ); i != bitratesForQPsMap.end( ); ++i ) { if( i->first != expectedNextQPIndex ) { throw NonContiguousQPSetException( ); } ++expectedNextQPIndex; result.push_back( i->second ); } } return result; } HM-HM-18.0/source/App/utils/BitrateTargeting/ExtractBitrates.h000066400000000000000000000061521442026013100241450ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __EXTRACTBITRATES__ #define __EXTRACTBITRATES__ #include "RuntimeError.h" #include /// An error occured while parsing a POC line from within a log file class POCParseException: public RuntimeError { public: POCParseException( const std::string& pocLine ): m_pocLine( pocLine ) { } virtual ~POCParseException( ) throw ( ) { } protected: void outputWhat( std::ostream& o ) const { o << "POC parse exception: " << m_pocLine; } private: std::string m_pocLine; }; /// The QP set from the log file was not contiguous. The QP set must be contiguous to be able to convert the results into a vector. class NonContiguousQPSetException: public RuntimeError { public: virtual ~NonContiguousQPSetException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Non-contiguous QP set exception"; } }; /// Extracts the average bitrates for each of the temporal layers from the given log /// \param i The input stream that represents the log /// \return A vector of doubles that contains the average bitrates for each temporal layer /// \throw POCParseException if an error occured while parsing a POC line /// \throw NonContiguousQPSetException if the QP set from the log file was not contiguous std::vector< double > extractBitratesForTemporalLayers( std::istream& i ); #endif HM-HM-18.0/source/App/utils/BitrateTargeting/ExtractBitratesMain.cpp000066400000000000000000000064511442026013100253070ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "ExtractBitrates.h" /// In out, finds the first occurence of toFind and replaces it with "e" /// \pre toFind must have a size of 2 /// \pre The first character in toFind muts be 'e' /// \pre out must contain toFind void replaceWithE( std::string &out, const std::string& toFind ) { assert( 2 == toFind.size( ) ); assert( 'e' == toFind[ 0 ] ); std::string::size_type pos( out.find( toFind ) ); assert( pos != std::string::npos ); out.erase( pos + 1, 1 ); } /// Formatted output for a double with appropriate formatting applied (correct number of digits, etc.) void outputDouble( std::ostream& left, double right ) { std::ostringstream oss; oss.precision( 6 ); oss << std::scientific << right; std::string s( oss.str( ) ); replaceWithE( s, "e+" ); replaceWithE( s, "e0" ); left << s; } int main( int, char** ) { try { std::vector< double > result( extractBitratesForTemporalLayers( std::cin ) ); // Extract the bitrate vector // Output the bitrate vector if( 0 < result.size( ) ) { std::vector< double >::const_iterator iter( result.begin( ) ); outputDouble( std::cout, *iter ); for( ; ; ) { ++iter; if( result.end( ) == iter ) { break; } else { std::cout << " "; outputDouble( std::cout, *iter ); } } } return 0; } catch( std::exception& e ) { std::cerr << e.what( ) << std::endl; return 1; } } HM-HM-18.0/source/App/utils/BitrateTargeting/GuessLambdaModifiers.cpp000066400000000000000000000367411442026013100254300ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "GuessLambdaModifiers.h" #include #include #include namespace { /// Formatted input for a bitrate vector /// \param left The input stream that contains the bitrate vector /// \param right The vector to be written to /// \pre right must be empty void parseBitrateVector( std::istream& left, std::vector< double >& right ) { assert( right.empty( ) ); for( ; ; ) { assert( left.good( ) ); double bitrate; left >> bitrate; if( left.fail( ) ) { break; } if( bitrate <= ( double )0.0 ) { left.setstate( std::istream::failbit ); } else { right.push_back( bitrate ); } if( !left.good( ) ) { break; } if( left.peek( ) == ' ' ) { left.ignore( ); } else { break; } } } /// Makes a next guess for a single Lambda-modifier based on only one previous guess /// \param initialAdjustmentParameter The proportionality to use between the target bitrate and the previous guess /// \param target The target bitrate value that this Lambda-modifier is trying to reach /// \param previousPoint The previous guess /// \return The Lambda-modifier guess /// \pre The given point must contain only positive non-zero values double incrementLambdaModifier( double initialAdjustmentParameter, double targetBitrate, const Point& previousPoint ) { assert( ( double )0.0 < previousPoint.lambdaModifier ); assert( ( double )0.0 < previousPoint.bitrate ); double extrapolated( previousPoint.lambdaModifier * targetBitrate / previousPoint.bitrate ); return previousPoint.lambdaModifier + initialAdjustmentParameter * ( extrapolated - previousPoint.lambdaModifier ); } } double polateLambdaModifier( double targetBitrate, const Point& point1, const Point& point2 ) { assert( 0.0 < point1.lambdaModifier ); assert( 0.0 < point2.lambdaModifier ); assert( 0.0 < point1.bitrate ); assert( 0.0 < point2.bitrate ); assert( point1.lambdaModifier != point2.lambdaModifier ); assert( point1.bitrate != point2.bitrate ); // Calculate and return the result double denominator( point1.bitrate - point2.bitrate ); double result( point1.lambdaModifier + ( point1.lambdaModifier - point2.lambdaModifier ) / denominator * ( targetBitrate - point1.bitrate ) ); return result; } double guessLambdaModifier( double initialAdjustmentParameter, double targetBitrate, const std::list< Point >& pointList, double interDampeningFactor ) { assert( ( double )0.0 < interDampeningFactor ); assert( interDampeningFactor <= ( double )1.0 ); assert( !pointList.empty( ) ); double preliminaryResult; if( 1 == pointList.size( ) ) // If there is only one prevous point, then we cannot interpolate, so we call incrementLambdaModifier { preliminaryResult = incrementLambdaModifier( initialAdjustmentParameter, targetBitrate, pointList.back( ) ); } else // If there are at least two previous points, then we may be able to interpolate { std::list< Point >::const_reverse_iterator i( pointList.rbegin( ) ); Point point1 = *i; ++i; Point point2 = *i; // If the slope is either horizontal or vertical, we cannot interpolate if( point1.lambdaModifier == point2.lambdaModifier || point1.bitrate == point2.bitrate ) { preliminaryResult = incrementLambdaModifier( initialAdjustmentParameter, targetBitrate, pointList.back( ) ); } else // If the slope is not horizontal and not vertical, we can interpolate { preliminaryResult = polateLambdaModifier( targetBitrate, point1, point2 ); } } double previousResult( pointList.back( ).lambdaModifier ); // Apply "intra dampening" { double intermediate( std::log( ( double )1.0 + std::abs( preliminaryResult - previousResult ) / previousResult ) ); assert( ( double )0.0 <= intermediate ); if( ( preliminaryResult - previousResult ) < 0.0 ) { preliminaryResult = previousResult * ( ( double )1.0 - intermediate ); } else { preliminaryResult = previousResult * ( ( double )1.0 + intermediate ); } } // Apply "inter dampening factor". If necessary, reduce the factor until a positive result is acheived. double result; do { result = previousResult + interDampeningFactor * ( preliminaryResult - previousResult ); interDampeningFactor /= ( double )2.0; } while( result <= ( double )0.0 ); return result; } namespace { /// Extracts a single point at the given index from a full meta-log entry Point pointFromFullMetaLogEntry( unsigned char index, const MetaLogEntry< std::vector< double > >& fullEntry ) { Point result; result.lambdaModifier = fullEntry.lambdaModifiers[ index ]; result.bitrate = fullEntry.bitrateVector[ index ]; return result; } /// Calculates the inter dampening factor based /// \param parameter The inter dampening parameter which determines how severely the inter dampening factor is affected by Lambda-modifier changes at previous temporal layers /// \param cumulativeDelta The sum of the percentage changes of the Lambda-modifiers at the previous temporal layers /// \return The calculated inter dampening factor /// \pre cumulativeDelta must be non-negative /// \pre parameter must be non-negative double interDampeningFactor( double parameter, double cumulativeDelta ) { assert( 0.0 <= cumulativeDelta ); assert( 0.0 <= parameter ); return ( double )1.0 / ( parameter * cumulativeDelta + ( double )1.0 ); } } std::vector< double > guessLambdaModifiers( double initialAdjustmentParameter, const std::vector< double > &targetBitrateVector, const std::list< MetaLogEntry< std::vector< double > > >& metaLogEntryList ) { assert( !targetBitrateVector.empty( ) ); assert( !metaLogEntryList.empty( ) ); double cumulativeDelta( 0.0 ); std::vector< double > resultVector; for( unsigned char i( 0 ); i < targetBitrateVector.size( ); ++i ) { // Populate pointList with up to two of the previous points std::list< Point > pointList; std::list< MetaLogEntry< std::vector< double > > >::const_reverse_iterator j( metaLogEntryList.rbegin( ) ); pointList.push_front( pointFromFullMetaLogEntry( i, *j ) ); ++j; if( j != metaLogEntryList.rend( ) ) { pointList.push_front( pointFromFullMetaLogEntry( i, *j ) ); } // Calculate the new Lambda-modifier guess and add it to the result vector const double newLambdaModifier( guessLambdaModifier( initialAdjustmentParameter, targetBitrateVector[ i ], // target bitrate pointList, interDampeningFactor( 50.0, cumulativeDelta ) ) ); resultVector.push_back( newLambdaModifier ); // Increment the cumulativeDelta const double oldLambdaModifier( pointList.back( ).lambdaModifier ); cumulativeDelta += std::abs( newLambdaModifier - oldLambdaModifier ) / oldLambdaModifier; } return resultVector; } namespace { /// Ignores all of the the characters up to and including a given character /// \param i The active input stream /// \param character The character to ignore up to /// \throw MetaLogParseException if the stream goes bad before character is encountered or just after character is encountered void ignoreUpTo( std::istream& i, char character ) { while( i.good( ) && character != i.get( ) ) ; if( !i.good( ) ) { throw MetaLogParseException( ); } } /// Parses a Lambda-modifier map /// \param right The map to write the output to void parseLambdaModifierMap( std::istream& left, std::map< unsigned char, double >& right ) { for( ; ; ) { assert( left.good( ) ); // Ignore the "-LM" if( '-' != left.get( ) ) { left.setstate( std::istream::failbit ); } if( !left.good( ) ) { break; } if( 'L' != left.get( ) ) { left.setstate( std::istream::failbit ); } if( !left.good( ) ) { break; } if( 'M' != left.get( ) ) { left.setstate( std::istream::failbit ); } if( !left.good( ) ) { break; } // Parse the index long indexLong; left >> indexLong; if( !left.good( ) ) { break; } if( indexLong < std::numeric_limits< unsigned char >::min( ) ) { left.setstate( std::istream::failbit ); } if( std::numeric_limits< unsigned char >::max( ) < indexLong ) { left.setstate( std::istream::failbit ); } if( !left.good( ) ) { break; } unsigned char index( ( unsigned char )indexLong ); if( ' ' != left.get( ) ) { left.setstate( std::istream::failbit ); } if( !left.good( ) ) { break; } // Parse the Lambda-modifier double lambdaModifier; left >> lambdaModifier; if( lambdaModifier <= ( double )0.0 || ( !right.empty( ) && ( right.count( index ) != 0 || index <= right.rbegin( )->first ) ) ) { left.setstate( std::istream::failbit ); } else { right[ index ] = lambdaModifier; } if( !left.good( ) ) { break; } // If we peek and see a space, then there should be more Lambda-modifiers to parse. Otherwise, we are finished. if( left.peek( ) == ' ' ) { left.ignore( ); } else { break; } } } /// Extracts the indexes from the given maps /// \return The set of indexes std::set< unsigned char > indexSetFromMap( const std::map< unsigned char, double >& in ) { std::set< unsigned char > result; for( typename std::map< unsigned char, double >::const_iterator i( in.begin( ) ); i != in.end( ); ++i ) { result.insert( i->first ); } return result; } } void guessLambdaModifiers( std::ostream& o, std::istream& initialAdjustmentParameterIstream, std::istream& targetsIstream, std::istream& metaLogIstream ) { // Parse the initialAdjustmentParameter double initialAdjustmentParameter; initialAdjustmentParameterIstream >> initialAdjustmentParameter; if( initialAdjustmentParameterIstream.fail( ) || initialAdjustmentParameterIstream.good( ) ) { throw InitialAdjustmentParameterParseException( ); } // Parse the targets std::vector< double > targetVector; parseBitrateVector( targetsIstream, targetVector ); if( targetVector.empty( ) || targetsIstream.fail( ) || targetsIstream.good( ) ) { throw TargetsParseException( ); } // Parse the metalog std::list< MetaLogEntry< std::map< unsigned char, double > > > metaLogEntryList; do { // Parse the Lambda-modifiers MetaLogEntry< std::map< unsigned char, double > > entry; parseLambdaModifierMap( metaLogIstream, entry.lambdaModifiers ); if( !metaLogIstream.good( ) ) { throw MetaLogParseException( ); } // Skip the ';' if( ';' != metaLogIstream.get( ) ) { throw MetaLogParseException( ); } if( !metaLogIstream.good( ) ) { throw MetaLogParseException( ); } // Parse the bitrates parseBitrateVector( metaLogIstream, entry.bitrateVector ); if( metaLogIstream.fail( ) ) { throw MetaLogParseException( ); } metaLogEntryList.push_back( entry ); if( !metaLogIstream.good( ) ) { break; } if( metaLogIstream.get( ) != '\n' ) { throw MetaLogParseException( ); } metaLogIstream.peek( ); } while( metaLogIstream.good( ) ); if( metaLogEntryList.empty( ) ) { throw MetaLogParseException( ); // The meta-log should not be empty } // Initialize firstIndexVector and check that the sizes and indexes match std::set< unsigned char > firstIndexSet( indexSetFromMap( metaLogEntryList.front( ).lambdaModifiers ) ); if( firstIndexSet.size( ) != targetVector.size( ) ) { throw MismatchedIndexesException( ); } for( std::list< MetaLogEntry< std::map< unsigned char, double > > >::const_iterator i( metaLogEntryList.begin( ) ); i != metaLogEntryList.end( ); ++i ) { if( indexSetFromMap( i->lambdaModifiers ) != firstIndexSet ) { throw MismatchedIndexesException( ); } if( i->bitrateVector.size( ) != targetVector.size( ) ) { throw MismatchedIndexesException( ); } } // Initialize simplifiedMetaLogEntryList std::list< MetaLogEntry< std::vector< double > > > simplifiedMetaLogEntryList; for( std::list< MetaLogEntry< std::map< unsigned char, double > > >::const_iterator i( metaLogEntryList.begin( ) ); i != metaLogEntryList.end( ); ++i ) { simplifiedMetaLogEntryList.push_back( MetaLogEntry< std::vector< double > >( ) ); for( std::map< unsigned char, double >::const_iterator j( i->lambdaModifiers.begin( ) ); j != i->lambdaModifiers.end( ); ++j ) { simplifiedMetaLogEntryList.back( ).lambdaModifiers.push_back( j->second ); } simplifiedMetaLogEntryList.back( ).bitrateVector = i->bitrateVector; } // Run the calculations std::vector< double > resultVector( guessLambdaModifiers( initialAdjustmentParameter, targetVector, simplifiedMetaLogEntryList ) ); // Output the results std::set< unsigned char >::const_iterator indexIter( firstIndexSet.begin( ) ); std::vector< double >::const_iterator resultIter( resultVector.begin( ) ); do { if( indexIter != firstIndexSet.begin( ) ) { o << " "; } o << "-LM" << ( long )( *indexIter ) << " "; o.setf( std::ostream::fixed, std::ostream::floatfield ); o.precision( 7 ); o << ( *resultIter ); ++indexIter; ++resultIter; } while( indexIter != firstIndexSet.end( ) ); assert( resultIter == resultVector.end( ) ); // The index set and the result vector should be the same size } HM-HM-18.0/source/App/utils/BitrateTargeting/GuessLambdaModifiers.h000066400000000000000000000165401442026013100250700ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __GUESSLAMBDAMODIFIERS__ #define __GUESSLAMBDAMODIFIERS__ #include "RuntimeError.h" #include #include #include #include #include /// Thrown if there is an error parsing the initial adjustment parameter class InitialAdjustmentParameterParseException: public RuntimeError { public: virtual ~InitialAdjustmentParameterParseException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Error parsing the initial-adjustment parameter"; } }; /// Thrown if there is an error parsing the targets class TargetsParseException: public RuntimeError { public: virtual ~TargetsParseException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Error parsing targets"; } }; /// Thrown if there is an error parsing the meta-log class MetaLogParseException: public RuntimeError { public: virtual ~MetaLogParseException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Error parsing meta log"; } }; /// Thrown if there is a mismatch in the vector sizes or the Lambda-modifier indexes class MismatchedIndexesException: public RuntimeError { public: virtual ~MismatchedIndexesException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Mismatched vector sizes or lambda modifier indexes"; } }; /// Full meta-log entry template< typename TLambdaModifier > struct MetaLogEntry { TLambdaModifier lambdaModifiers; std::vector< double > bitrateVector; }; /// Contains a Lambda-modifier and bitrate for only a single index struct Point { double lambdaModifier; double bitrate; }; /// Performs interpolation/extrapolation to guess a single Lambda-modifier /// \param targetBitrate The target bitrate value that this Lambda-modifier is trying to reach /// \param point1 One of the two previously tried points where first is the Lambda-modifier and second is the obtained bitrate /// \param point2 One of the two previously tried points where first is the Lambda-modifier and second is the obtained bitrate /// \return The interpolated Lambda-modifier guess /// \pre Both given points must contain only positive non-zero values for first and second /// \pre The given points must have different first values and different second values. If either the first values are the same or the second values are the same, then we have either a vertical or horizontal slope, and thus, interpolation cannot be performed. double polateLambdaModifier( double targetBitrate, const Point& point1, const Point& point2 ); /// Guesses a single Lambda-modifier /// \param initialAdjustmentParameter If interpolation/extrapolation cannot be performed, then this parameter is used in the "increment" process. /// \param targetBitrate The target bitrate value that this Lambda-modifier is trying to reach /// \param pointList The list of points that correspond with this index /// \param interDampeningFactor This factor is obtained based on guessed Lambda-modifiers for previous temporal layers. In some cases, this factor will scale down the change of this Lambda-modifier so that we are not making too many severe Lambda-modifier changes for a single encoder run. /// \return The Lambda-modifier guess /// \pre pointList cannot be empty /// \pre interDampeningFactor must be greater than zero and less than or equal to 1 (0 < interDampeningFactor <= 1) double guessLambdaModifier( double initialAdjustmentParameter, double targetBitrate, const std::list< Point >& pointList, double interDampeningFactor ); /// Guesses all of the Lambda-modifiers /// \param initialAdjustmentParameter If interpolation/extrapolation cannot be performed, then this parameter is used in the "increment" process. /// \param targetBitrateVector The target bitrate values that we are trying to reach /// \param metaLogEntryList All of the previously run Lambda-modifiers and their corresponding bitrates from the meta-log /// \return Vector containing all of the guessed Lambda-modifiers /// \pre targetBitrateVector cannot be empty /// \pre metaLogEntryList cannot be empty /// \pre The size of targetBitrateVector must be the same as the size of bitrateVector in every item in metaLogEntryList /// \pre The size of targetBitrateVector must be the same as the size of lambdaModifiers in every item in metaLogEntryList std::vector< double > guessLambdaModifiers( double initialAdjustmentParameter, const std::vector< double > &targetBitrateVector, const std::list< MetaLogEntry< std::vector< double > > >& metaLogEntryList ); /// Guesses all of the Lambda-modifiers /// This function performs all of the necessary input parsing. It ends up calling the other guessLambdaModifiers overload to perform the actual calculations. /// \param o The output stream to write the guessed Lambda-modifiers to /// \param initialAdjustmentParameterIstream The input stream that contains the initial adjustment parameter /// \param targetsIstream The input stream that contains the target bitrates /// \param metaLogIstream The input stream that contains the meta-log /// \throw InitialAdjustmentParameterParseException if there is an error parsing the initial adjustment parameter /// \throw TargetsParseException if there is an error parsing the target bitrates /// \throw MetaLogParseException if there is an error parsing the meta-log /// \throw MismatchedIndexesException if there is a mismatch in the vector sizes or the Lambda-modifier indexes void guessLambdaModifiers( std::ostream& o, std::istream& initialAdjustmentParameterIstream, std::istream& targetsIstream, std::istream& metaLogIstream ); #endif HM-HM-18.0/source/App/utils/BitrateTargeting/GuessLambdaModifiersMain.cpp000066400000000000000000000054451442026013100262320ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "RuntimeError.h" #include "GuessLambdaModifiers.h" #include class WrongNumberOfArgumentsException: public RuntimeError { public: virtual ~WrongNumberOfArgumentsException( ) throw( ) { } protected: void outputWhat( std::ostream& o ) const { o << "Wrong number of arguments"; } }; int main( int argc, char** ppArgv ) { try { if( argc != 3 ) { throw WrongNumberOfArgumentsException( ); } std::string initialAdjustmentParameterString( ppArgv[ 1 ] ); std::istringstream initialAdjustmentParameterIstream( initialAdjustmentParameterString ); std::string targetBitratesString( ppArgv[ 2 ] ); std::istringstream targetBitratesIstream( targetBitratesString ); guessLambdaModifiers( std::cout, initialAdjustmentParameterIstream, targetBitratesIstream, std::cin ); return 0; } catch( std::exception& e ) { std::cerr << e.what( ) << std::endl; } catch( ... ) { std::cerr << "Unknown exception" << std::endl; } return 1; } HM-HM-18.0/source/App/utils/BitrateTargeting/QuickStartGuide.pdf000066400000000000000000002323551442026013100244350ustar00rootroot00000000000000%PDF-1.3 %쏢 5 0 obj <> stream x\[km+w ,6x9~%R) hpH@KSsfö{Z]խT/o?+'Q#|TRDo?}wIuo~k$l\ cD+6.^'_wol$Ox EnAQZBc7慎9zieww{{Rݽw6=Pk׽IRW?FmSՕsi*bw{`4}{S }y^| @A{o`!}.pp'#9r,0J9{-Np@7Cp-Љ6DJD hꅔ@+o2mR)bWZ30<\25ъZ߂j[ vz(d]ʺ4w[[Ao ;:#L$-&w>HLh[/]FL,l;2r@3fKZ'/mu/X{Ӑ8 3Ž3L>`Mps9+st.T@o]l%g@0ȉ1T9:+B =NC}5| ~eᜭ ۫`u,q4\GRtP[(~YBSK2>Y &%ҠQ@a?16 5L3*Do`8S0^XmF Qz48/)Cz@@_Oؓi F#?#H@xP -` 4T?ᘭeӔ4w7LH'#gTT1iX(|i-PA쟌EjԦt|72EF,qw2!lع¦;72F!}Xlə!)Jq*f%y6*M d`spN;a2³"*)XXY·jVʊrycdd,Q]١ q|Ep04>5N43(( 5آdd[,sDWFAkj4tU&?A'BVѪds̈,*[;? ;5f|"H0CK J$VQE 6vCF+@익!ZӠr *F4@TfQ0F%0alR+=QYʳ Kŏ4ѸYQdKf`hIk~`2+D J["frWN.ZDWW^md)5ݠ~U[S]֘iBod$t]c75heb-^eUF[.\et`ULyd *& g/`;:ˈ9@|xh6k]EGH݇)yl( jJW_UgVWƷm FC0¬6e$n() s@{\D^jIHMMveQ{δX n;~Ip0{crl~h␟x8|[YJ!% a]K %K8dM=DuvHa_'w8Li@RnT,[,U^MR*1Yw4-~T 9ҭ рzQWL*m@~% W4 Gjh_L{9 GF*ٳb\T7$4#Q\"ڎ4:Xio'Dy"@ $B|XڮyC97%:c>B9/ 74RN!.wֻ`wwЧ>\QR {%Gn([t{q&m_D5L,Tʒ6;YWXtmw"^Cq1^=$Ҫ0QfS֬e8LVIy;Z +e V߂7;p@켼 'dB%aVV7ߊusy28cY2HWdrޞ]e[4˷d8:߳sk$ܬCE ;DNtbW/Y릡zA M=fehvZe"zz\yL1la>?@~4`fRBh $/w3F%I~ցpt21;;OƤtSi[/w]TJF)FR<; wcM\`i/CN`E )P!E[n@UzPul}j66.&~/Nֈ n J]OQӜ.A,bD wp$R3vS>?'q]hrwzѪh ȳikE0ؘaPv%Auh4V.kM53'g.ŭ2вςc(ǪnbhB%U3;*77 %xЊ: ,$Z߬Yl_K3̌+;6}p= _kn#j}[+JކtkY+ocRwk|DRVSsZzRK`kS}lxY+7ÆG#G |OOk!SJɈL;I ^ }ҳ>gK֚fd<+PʌٞCcN4>A>^y v%=6Dv!Z Rjj%22<{uؐ Jή<.w}Z}(%M׽VeE1ZQ/&WNKT ׺O;ZgւUnL`C/\ :T.B ER7CeLgt{Þ nz/ۣ>{KuntLϞzu.Ju**n8%P'1Loʞ!7k ̿/xye;O$;' ݉W?L=QԐ+ /ۛ;ֱdx/< u$w>THu!_6\ŚWi.Bh=bOjKBq̢x 7k#a9zxM^^LLFV!uG"3p? <&oOO끟בԒ3N^|"Z?y@h-` _OQDf> %njW.B˓ދendstream endobj 6 0 obj 3953 endobj 25 0 obj <> stream x\ݏ;r'c)1X!;wĉl[ȓXd$;ꝽsVf?~q%:V"ͅ~8y_}iы;+| (ۯvOB㟡OZ0 'U׻ſ"ʫsfu?ַ73ڪ~faXplN9c?/>yyq aCa%0dEWzi5xUwZ҄Vw{U|Qj}f \Ų%uVdZU:?݈NDO޿7 f-C+uonfQ Cߓ)z-E_>JLItC^;וI:tΧqR[*SooLn8^I?z]!|Xj tv܄ t~UJǥtPJJ w WQ6K+3L\IG44E1kM'z1>+'aS*X`wK)M-Hi)a',tXJO1ˎ 5FYՃ\ L2;5>+Þ4>W8II2mnuq~orPr t6 wj0>;fb=(cPDgZc3"4#1[mp&zY4~4gp#ʥO7u@{AU$"ԜCpGb3FkN;Ờ ۩9%]+32|طGt{8- D fcu3cUmJ.c&Gc&f6rXa} ΍:+o0!g@wŽ|Dxp;CiJ3G>ts;`NҀ KiMXZtiͪ6RwtK=XJ{\>1,- ! L]-KSADf#UTZlnƗ daF{|Oh-6 !^lʼF |^!!Ejdg >( sR! 47C+j1dpT"NH6Nu%…z) &CzV/I_Ej>VEA-V΍;zaAbDt$bJQC8`{" {[EV9tnne%5v(E 2-O:2)0E%mƧK!&u ,_;]Df2ŶhToTvqprNHۆfsL12|&3$5 YJ`d*R6w'ENzcC`3 q>rZ7[iiafFY#\:DAK>y.}p)/Z*|ڱ j_鬳ًb{x%<}i'џVt0]W#}+jh g ?P g%B.q[aO 鋎B 'G\qZOT$eZ+AoӽKٷ):/rȾP;?<uUU&-q$i?:.)OZY=@Ƞ _!`6%>|V+9\&}:K"l*W"SzOu< IATE^& X;il`",#mn9 Y]g[\vcRJ@;$0@OW!hyЫ|FRbWZB>sE=55AEsB2cV`G mF$л&ѧsyoP"ey(0 ̘]&IpG$ο]KS E3[(/Kne<6bbVi#B(i_%2L_3>QXa^)y[,F?o`5h ȡԾ[dTdj y\/04¬m55l0e~Zjt#nI:G&Dah}%Kn񀩧F,VU$ƈc19̸5>O/Fihz zLH"SN&HkwRk#5Ήo ˖EG޳4Bq/GL,BqzID䙦tbja̶tzhõM}Fݹ>=xi}'Y=}Ir!¨+6,Ÿ_v䱏3]"jm#yᄆ˝ޚtr~7SO'LDNؤWVDw [:?-H D>6x=IXd@c*eIijتBNpZktP/ RH g9B̂ i]٥%edpYE^LGsͳ lT%N1e/ʹ$Mt4D Mň _vOࡡM3 mI=b2"7p uojאM40fTtpS $v G!|=ͫ'H*]͡5q ֦6饄`{C,qNFȱ? -V!4s2k'mb'1(o9}+7 +\ytwkX#`nwJ xiHU}t:aTPyGO6$.;obɻz7D`}Xn~p*A9Ŵ ipUg%FFTaQheZOӼ?7S^WY0 RS].Rr>Q46^+ҸTdvX^ ʤ3EdiKne_q> s d jLLo=+jKq^e׊ý@1⍤i:KM1l@%бIV;VӖ^=y^u9_ɜkߥ̷q˥uJv'}3-ir7 zl5݅C4cjwZkۮV R{LS߳yN4 rKK > stream x[ߏ$7 p9d"nt 9"S<%ڷ;tH Dݶ陹큸{*|Lŗ/>U⛯LOQ?8 sR˫;?eh}p`ϙqZ?|/^ ËoA )q/V^1MoF2܋f#g.(\{׃ -wbK>:}\(aa9iVo~8A{RCoǽfFy\܄c8_=vVg\i 1?#twZ7`A53jf ͞np_p- |B$Yi0TAy:=^>ؖS#@; ~T4؂eIPnlBYadx=,S6n5~hȐ3-Q~Ujk/U!\z|C\Wv h#BȪEj1?A|7N_n%/64GLRПAJ"ڕw9|q@xH#rISl8Rf,1{' uwq{y]DOFVuKDT Pr *O(9|k˵~B|ZOxςvTb4· "sHNC@À\)?=* \JX9 rrge^,F[caz`Z;,a2)wc*-Jࢱenj95s;@>о0ţKRKBu;u-_.ozF5X6 @ޅF J;)YDM̈́X E r4M=GZ@v5HKy0jzk'gy;N <<|0N׮3wgH!ͯP䐴Eט_q/r;kYdY5x mMkr^;o_p@%=j!!ȳ[ \vX“rK.")4I@yw{i-Z$AKt/@^>HW#O š)D%;`Aadp0a%>E0 "-4b,7?i wE+R֫˨΀V9AnqZ5%ǰ)g]"璉pϵL/4leQQnh.hl硜iXDD1_="? ?Ghuma/ Y$ԅ̀ ёc 0w:~ήyS^/3_&L"l ,YGG&!9`3Z{dI7'%'b‡ʖDIn-YVZjϕpezGE|쳵`>EH3h ,)URq+CRVL4;Aamɓy"w:r*4jヵݮTvQD@KkL2MژJWu2 6h[=HȅlwCU*KXuK6h䚊MeæVʍ+ǰc&ùo1W..Sem#2M!bUǯh> |u&9?a%2La!M}-%«FnD&I;1 jK7@h4 HEifl!SRq%D|㈭!ЁtJ,FV,ڨ;l&"qdhG(%)MM9q๞u)3-'A'nH$4a!Z :qnyYkVI|q *Ë|CU6G@ey@iQR  #eEb/d ߃b]2'\Qji`Z4q< '=ryd zV;ԶrgV$d^*WBfܦ`4\=dܥ#ΧL(9%bpnR`GXvE4~RzPX(0Hf*3`mfS&:9SYȤmU=> /Contents 5 0 R >> endobj 24 0 obj <> /Contents 25 0 R >> endobj 29 0 obj <> /Contents 30 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 24 0 R 29 0 R ] /Count 3 /Rotate 0>> endobj 1 0 obj <> endobj 7 0 obj <>endobj 22 0 obj <> endobj 23 0 obj <> endobj 27 0 obj <> endobj 28 0 obj <> endobj 32 0 obj <> endobj 33 0 obj <> endobj 14 0 obj <> endobj 41 0 obj <> endobj 16 0 obj <> endobj 42 0 obj <> endobj 43 0 obj <>stream x]ӱn@^_?<ڀpݸ$<*L\=3kH1Qz5ǟu]orY~\?6vY|nMq;~۟[mpC]k5u8}\R9-K9uRoIy.^")k[")YIgK$yb8VևICX"ipֱDRX%:]J$GֹDвIu)$ n&3[>ـ.  8p Z ;p7 V /w`5y; V / ɛ'VX-V#`5y;}&oO ^AV`)j-.oYa{Vauy3auy[N尺ƀu_ˍuX]^STz_M?B̢uá`-^r*LV9Iᑻft.ux.kwtU r endstream endobj 18 0 obj <> endobj 44 0 obj <> endobj 20 0 obj <> endobj 45 0 obj <> endobj 46 0 obj <>stream x]r0 D " /%v:m@5swwz2/_^}8?nvqmv2|9Muۀvmzk)ginǴSi]mJ'.gծz 6֮Pm](x]!m]!v+JXB.^d\BiJm+k %)Z 23 p&4΄0HC&B@C&Qg@!uZИk1%UQ"D+OB'0;tx'b74.L"kd{> -X]5;X]Qgu`u&NM: V﨧`ul;8$df'(qkod7pBU0Xx#y"(!D257ɂ57"R聄̜~ko#X)W`t6'. 0rd蟄`"(![,!3/BirH/*3RTfcx$\n`9}|H8;>h]KKK躵{m<5@?S|2n endstream endobj 8 0 obj <> endobj 47 0 obj <> endobj 48 0 obj <>stream x]=r F{N g<8d2I.`0b\a(E`\_)n{/M/1BY]Pɰ(V kSjC| 'J[1D5s"Avm endstream endobj 10 0 obj <> endobj 49 0 obj <> endobj 50 0 obj <>stream x]1n0 EwB70R\%C ?ש48nҴa^߆==i ס\91gjJێK~.E2;PUOݑȀE{2 d@]ɀ؋ɀ=A;D/d@ȀGd@*E3%B(Zj͊7ʭfE%>֬y^fE;֬y;vs\.=֕˦C!2/Uc- endstream endobj 12 0 obj <> endobj 51 0 obj <> endobj 15 0 obj <> endobj 34 0 obj <>stream xmpT{}"B>&"BL6n@VB`ل$$0h\$n`*og5+XRȾv:?;=ι{[ =ažvogN‘TߌS Gh]սf=p @,܀G ĩ0LP Na= b/i /T|><3a4!' mLB_Y"GbixGZx58EHy|Nh=(61G>fkgF<%p3Õ W>^C8#d&)'ZG"OR =Dϳq,07 ;'#j :%b&kqp=t 6`BBAxDx>ON)P"cI>4rb%s"ri%kv< u)Π3i)OVIUi?2fgk؝l/{c  VAA>_ aDaw<vi9Z֤m0Wnr ӀYrN"tc6㎶;!/b}ޅq1ap&3)$1אK1O]d!}as ø0p1ui@:H0fBcDl [ndk6%{`!6P&4OxSx_8,NE?*/' ɆL 2n&a.kH~KN2зaQ T`5|N&Yd d9Yfl.-&N@)l QF9ڠ<[sq$SX1C 0LKAMA$F+eeR"R'SJ$sB 'a|nCۡ 'nM=dE4c#I#մ+n/`{pCo ~rijw4M{jmd3*>hja%?'9S+r'efML2>9ɔ8.!>.6F2DQv#9UQ)EGU7VG=̱p4{\>=q)ZJ+A5lnf 57q>_&E XrQ!5)ZCŹjDSR., j$]V7yЄڳehkŭR ]LX%=%= Vs?&R/є:VDX%hlcdTk],Fg4R,G9Wln%JC:X. ig*}vYM2.Cq/a!:cdxk ]^Rנ {]ZO;8eA`\:)p,~*A+@.tNBttGIa+C).\xqxI=n3ozQ)>46&W\$ܤ:qǴ(++DCA<XfdMMΪDk#{ҳbߛ[[Q {.^܎:fAj*0O!RbRbfB䠵xo ci L5,@10Ř"%K&i/JdJ #V PMc z)(~㙃:5ġ$gJbuJ QhISK,Q[β8Tc2W>7rUڋYktY3E<hfFGRҪ+Jl߁1D#b-[u< 5n0q?\x2TSgrs/@8?]  tTvG9LTdBvR[-5A}wdP=YV$Ü[0}$ >͈1 >R^IUżzيy }I$sd6t*y!}z= q`F1BF!=> 3T;=}I1(W\=cUũ>L#~w_;rç`+'.#k\c >DC ǯ}8ۛ:Vq}Hƒg6} @n{ue ~O㵀TpSbH<1r>> endobj 35 0 obj <>stream x[y|TU>WK6RHBRT  R!DDBъ`&cT6QVavWpQ{A?滯*837Ls9w;[&bDF!4}VY9-i]O&]LC΅K^2r:/ bw.xoљA"slލzaǒeWD{]50Q^dI=#J%ew.ZoK;ޘٴre9Q^5Yxzzel~:5l meaB~\tKSJ-hҥ\gt~^@30?]XY/AG#fb)lHeN6] Zֳ{0ۅQ+5󹓏r~ ߉l1Jxx1YRjzB|)q.7m1m70=jztœj/xO?}OkGwy;o.^XDH#D"bRlxY/>߈A8Q[(Syr.SSS%%Q3-U& yݖ׭Ad~zD']X%| * y-82`kl/4]a:v X#EÕGPLV1I|9ͩa'bGD#̢C*,&dSJONq=..aGufV)tdQ [t Z-PˮOA<cL#؋|槰]ĕ p'i9RG\LSNf< t4WBl)G]#'ʕUZӽ@M2ll@aPA]enQZhư)/ϤU_H뛩Fi[5uR٦~Ԡ0[_DAReKaME:Sn[#L}4ޭ7N,:h:=IXLjkUjj3eQ"Z˱譛\㭮I'T7N+-9u5ʩ: FrsF ?%3Ö>,-5%9j1\ AUs5:T]Pj*T C}45hC=?yzcAOfS'R.5C^_ 1Cfț 9 Ӊ/^XPi u}ztם\kO.-)lWg7ˮb}9Y0)-Ur]r(.Кf}NgDcumjtBu0Nèj&/.jAOׂ&Zr ƭײ$*:Ϭ9ٚ/¾EkTN􁶼!nY*F~Ɛ\\Ul}.Z^ĭ k4Jg$/۫<nZu+ZoNWzܡҒn[F,BjB͐ w)5,3r63񻰦 Op 0,Ғa$5Sͥ&d?jZsk̓T}@<Xs2KK.rӦ@ m L*CNyozi>*Zh?VWi~~eƃ7`1[ZBA2y=n:1IcY=foj1ׯxlb R<.|aX-βOՔ"^X -85NlOVFs4I!!K Ls!6Zl2NNx2&H5/BV'1U:1?.p,-iF7Ԇp0C]g@D=7k USmekgpVXp낵B*rJYQeV?aU Qo22t(l:y S?9{G2P*?p?lﯲ!"5i~ otwc=?:y/5S{9O1tbL3+FJ7*\=#kJ /vm+DҪKQi#=:l5E.b": ^L𓚥J`p°xEvdX=;rQ,ܨƪ-՞srڌXYVmRq1irtI,*29&KdaYx'8R:cx[ xEfO|>#`88>"i5\) ~,fzeo-v?}?9x5f~tTT>8`{2[ .jm],]tw;k彆) 2ʣwcQnid^1h):9ɋQqq]s:4c&cI !  @^ޠ/XCw& @ F2(_( PG T; e&tOaC;xP L3GE82^:`%xFs|wC'vu{[*{fH_I2U I2H,${CnԼpRGŜs d9:V?mRҚ|?mOG7h?h?:ُy@p3Ga ^TqlL8ii|;'=]~<;;fylSF;K/` ^AYYز33Q۴~FI5I|H#q#6ˍF:춈{f dHnVrudr(#9hq8anwOۣg7ը"Bn/E<2{Tõ>u ">q0 wMwtuLEo/v)xbb1&;n *0:]e2'rKiqXFZ-íVu5՚lZVʭdՏz=Sqp4++l(gVcvh䍳jYFUY(KU˴Fjl&x}Vi,Mw3!⓾eTΗg^b,c|Yz} @9YUTgVeLlsWyq_{dd@+>2Ш<| _}/Rb_fJlG*~Ș/ ?+>ւ߶_ïPKJ"ï()S*w>*u>]>STdds +$}*nKpayd7\,pKYAI;:v>_{z<2"nAj7]֑jw[ ~suȲ] 6W] itwSmTz+}@ϔqCƺqpqMYlkJ/+yBU!ǚbEF7T9({xJ25 f:t߃cS*i4֔H)i&OqSΊJg#nA%ϲ])Ƿ>Ӆ eec]pЮoԊg5jx#X %it))>bӠ$B :JdKJ;<^ɧ 0o[F]46slcKɏkk~l{?],n~wFTTE+!m endstream endobj 19 0 obj <> endobj 36 0 obj <>stream x| |Sž9ٗ&iӦm(MҍMB[ tJNZE@@(" q! -"p^Ԋ\A@3@}{}އL9sf~ RGEeD$|eD0Bط~Tӗyo "$mj7 y%qg5[Xscm×C`J3 "O3i1p_)ԟsRd ɵQp˔֩_3r_cKXt"B&ԊZ}e؆ ڂv-t Kp >b#E=Q<=UCD|G_Ks3IO5OU4D\HRAvU$^"~N+ Pa`p`"jBcP5j@w/c*fh&" ZVw磅= Z !=BސW qIK DmϬFkE֡'zzB=%}7&imLn@;n[]cp]ȃGt`-xkTV)`Va4-6O|f> b 6eGRr:ӲIڑܼGz3P[r=h/ڏ^Py*4>!sw;tB/H@ȕyw!zz}>D OЗt }v8 mr}Eߣ #.+F7n%-c8Z_3G>k1pW=қ5| =⩁`$^_dw{$_!D/﹂F:V=YQ^VZR\4|! dg92f OMIi5jB.J"(6ϒ_crEԸD8B@m5.>T#D3>b6Ac:nZS:J5YLSU"Rir]0A"%ͤ,;<%N7:91.9W; ؝X̤j́uX /7fµm\jrˑ Qk^{@%38]VKKoɦ D`|SxKB5ާ\ּ\R.S^[M.- IRD/ړL=6*I9\9(ymΆ&Whgi4`JE3 9 OA"Ke&'g+IkA).tEMNlD,AS@nќL?N2]B2|ihlR(S^cm]boq99b o4gŇȅ0H+\4Z*-ЇNR7bk} ,%Bk{{I|~@̏16Moۦ6l&L0|ƒ&̇͒_k1iMm= $ 6K3(98d qayv\,L<݁rvja0S]9;M0  %c"R)xdB|c] ;0d, iYa"Z( sm涚J2P#| ["g؎9ʥ4flI3iKW !R[&)MNdĴ$ISGOO|x 0/@ ׂZRT$JWBe B.9 1gH_mǵUC2uօ ,iג( LP6T!FBfHRkL`m/~N'R4|(h0zo"R->\V AGƣ8\ZYI /z#@ZJq)u`R.GI2%2Rh!%)vOWB?{XF&7c4TJj=ZfoZ@:&2vBFmwF U mm2?@%Sdhʃ%}Wn,'}0 Qih80 3D&+CLfyaD7יoL\eW&0 ?3w&~b2&goL|ķL|Lg+&1%]L|L|Y&ħLO3g8Lb#&>d&g=&e$06o1&o0qL1&^cU&2qLLb d>&2 7LċLdb/0<1,ۙxmLlei&0&3$xL31Lab3t&2}LLab2&ab<LcF&gZ&jD5cbb4L8&*(g&(bb8Ø`&f" Ld0ƄL2D2ILؘHd"x&LCDV* j E[ ኑS+t2:>b\\SEc\CE}\]EmbM&X]:(eq<" )Ûoi\IEq\QEK)S UTdeU8:n&Mp'95푫?ȵBܽ{R^w ]% =<)ݠt+(]++~h;(]tҏ~tJS(}KJ_S:O+J(}E JSYJ)Pҟ)tǔNQ!(O=JR:IJoSzқޠtqJS:F5JR:JÔ^2CR:@R;0 %J)JnJ\vSEEJ;))=GYJ)=Ci?QJiJ[(mS6R@i=')5*J+)=Bi)-6 z2JK)=Hi ŔQzBJ (ͧt?yRCi6YfRAi:iRjt{)PBi2I&R@J)5SGR#J(R4R51(4R%%;h$*(S*TJR1"J) 4R!!S*4R>x.$ۀo8x *(\^ 888t^P`7`ENuq < x 'VӀ-̀M2G^5%I:g`v>F0^c ;=.Yh^ /#WG(d Ulv唻tͮ_b .t9-!ٕD;!Aʘ֩ZĴiS[[.L S5@L:-f*[ Z7Uȭ1툼x8\p @)/O| 8!N x & qc^ 888t^`7EN l< x`#``=I:<Xh<XX C0^X #0^007\fffฉZ&&&&4@=P T'`$`P(Ea!|@6 d2i;? H$lD@ `C _W!'\|F#) E Y$Q?Z,X 4eZ^ z2X1po_Z2?~.}֋ztqx3}8iKLNY,ɶN 'a䤁-&$:adc#&_ufN/y:[@Ώेy^D4ÝQ?(2&`'իFϫ Wm}z{tX3>U\ωcP/ǧWrCʰȶ^b?}ڹ\9/\wiO%AO%#",a>Jʟ{j{ϙu~pƂAFU=%dB&Դ;2*o˳<O$h jX'U ~YodԔt  Cr&QHc<&ݳeK+ꝏaٽ`7M]%K$7=A7*9qYVBgڅ3C^ ..Yl\뙰3p(]&"UrL2"J%{sdIiP1On.9pQ$!\)I:vR)QT_l1Yh@lN=ٌ?|x>q7~q%k[9.Kd`(Iv#}<,k#Dɔ yFCtsR/$NR(#%ql##`O>6/g`N߾6ePPKPv52BI9$4u2i$K̴s]֮DN yi6짃vgE!_I$O5+7<s`*C~(9BIW NmV{[I$t:MI!Sa"xy礗8<72|Y# =|vQՃ- 0Wm=6dS?|ͳNe C)hH'm,q}b'6j@9Tq`׽}a٧N 2gZa 3vPq?f"  ӇV QQDV[4e?a1))cvo ~~Ģ ukJbml] N<4Hۯy垦Es> }uUKsQ>G?:J|\X%-#,.2%tP ;3^hTWx[qݙ;:K M,<0Þ1텉NM9 h1J#__rt=/,ϞbiΔRz7WCԣv1lwRR#~wEW( EA6瘰[^Zs;<힗q|s!W\S7Woǫ=d[ih(A+!8BGaP02*aȄ(l8߁y?0j<oeڔSN)F ح1tvElIUjȦ8hm,Itqo%%.J;spDd]Xojo^=2s/xp:m0;&' TeD+V;snenf T$'0-cR/C#93stJdX6UxCxC--T;!Ӝ1@,CZ҇G6T[yN Dv\*`UV)_S,Ao1o~2)NSdW)%Sm?bKFpۮ]ص۸S[M%qr}_Iv@Ìuip7 aGg49cD+X:zL B$M-6ϻ`# _!!!^Vxfj1H+$!(Pv' {rx"bR^)H\&Z :WR+R`#' ۰(GO]=Q\p%76= l)Gѝ-t^[([2V۫~{UEWV^W^MR5QC!ǻjL(.fZ*]w%8$%/sX->)YsWRs#|Iۋ L!cs;W+@)IU9d(QhKQٍV V2mwil)t w9G2/lMʋֽ}/pBorayi7SdgrU\zPukvss_ȞwQC' 25tb.ar؍7(#,chZ:vn_rQ8G0H*"nmH^a1Np̀u_mҀ I.;>~l® BXH Ƕb '{ JsarP֣ `)jꥧE-tMSN\uڧBAS=yW{ m ?rwmX,}k㮉E^ksμUcvcɂ*=ËdB9߃ Vt2+Q]Ew0b%u77+_tn|Zˊ- ] 5oX<#(uDF2:. 䚌:Q,޳GoNb9C A}"bbءجܭ>Wlv@^^m@ 'JEZnћX:ڴԹkļ~G綖GVojx隔@{Sif\կ~KPpn1&2ڨW;F z?j4FE󝤦}EܮU'@! YTJ.B we;)ska"l?#D*.n=L?opL֖h;9գX98A%3XvDPCE"5gmH,>M6qp?QWR\aӮ]>co`CЯ O%"bLԼH%WERE%6Vզ=R^KP BWK),9Tv'X"XEȐR))'X҆k#_Q7˞ϊϱ gx2;ZSFy!G$ė 5y|_qCs&^+ay11UpJۮ ([ .&,#.88.#̒N8˰QO%_0vyZags2;I/p#{ 'Jء(С@_J8Iq&قݥ۹]%mT<*a?nmpXO|*Beo/=~4I4Ipbi~!>L?wB Pt59)5=,~"v"P(J"ĭ5"mԸGyq qc"!"2qXǍ4273:9vơ RY$I69*7/jn7]vj}f0BŘlN "R>sCvm N^]|E}wž;h@$e4io*f׶.49!I9a#3#+F~mMXW+dD(r1?hC~7z9z@^]¦J]JD$͓!Oxu"Io3fE%he%Nt(M?Gxkm-ٵ*3a9&Oc3ӒCEG5ž l VšR%(c8k#177`<[ױɻc~pqoYlا/!}A )sYH͇,IG<]M!q s{Ԝk74-'o_o8>u]UQqƭM 2.|96`y55x:vsqz!1A>\!#?vú7LQ|]␪ >!Yly1{\Ń#) {g)w;U*_ )U?E[gr4Cw:'r>ːMX2Zh)q֢CHQFkh5W E/z=h z=HpEsh17+F2/F*AZO!m_Hi.%+Ep+ k`9S&NX*Ax~d.ބ 9mBUhzSpSN} d)hQG'&4D5hRQ.Q&(Q]ux 8ơp%6urᣘ9LAP r9yז!ik_N +o,~\> endobj 37 0 obj <>stream x[{xTյ_k3wnx Ϭ߸-V m_Jg)*_lӗ׵{s>Cu[Gw;`Uİ!0v'v蠏kx 0h3/qZEoz T9=K>JML /=B__R'H]$":(]$ hUAoP^Q>")\*绩4ӣI- &WXR<U: E>C˼i7hЪB=:A1[վa}~XA_̜“7M4|ǵg1n.]GN'.*~]xDd%y8vhho a;Zo{mODNC,%[>"W!֋~ȓ2Cq=ڏWqjPu+= O:0trG40qGwG!q\KM2 7;#|MbWReRnW$W/g^0>G/DǢiIQ2S)| x=HO ?҇ψ΁cjx~ec|Ư;|^00 wAX9<.5?9Q29UVfs||G~erҤP~bUGM{MM?5l7#>ApW1R(x]x.qU1'eHdJ5.NvKHC|KeDLqX.!z_Kb.2m<)rRoIƟP5Us% ڄ*=ii+|ly9Fhu;;A^FYSoCcZ/w.oF'o Ѹ։Sν/V"mb%)X8M\ۑ{y^t?=mj %yLT8qxwϻ.7';+3c\شT{[rRbb6)R0չCNubHU&-6ڮT'D#mTg0sr_Yblwz[\s;Փ~3Pw9(16].4peu*uj޺݅kݵENLB1 %5J6 "nfXNvuT9mڸ8PuE*׮tQS< èZb \φᢡޝ;<ɫܫZl cz0_~֧UtVZmZԫ;j]: ڊ z Alhrb4qo0ҩDUl~:]ZT5u!,MNJKnwSm]jU;.NKn9GjX`cRd۵:d륆%W#˺GyHչ On̩B'ԻfV*Z56kiH?% jGEY՝ԞOOP!]3tE3E\\mr#0NNIg뜩rQw MκP< #j1}U] \/\ihWJ YU&c6zUbEVv֫ &\QD2اn3=#FG+2Q44/M[vz"ZOiw2.teE#\~gVA5a7?8xy9ЏMm&]`I3T9502'G];C2dȬWdL+#"&2\/"Nju咑 ^KU.E٩O%jN0Cre/6`cƗ9q"wOd_,GJuLA5YT6hfx+8>x^WyPF{! ^FW})q Չ2(<Ɨɥe!قtlm]dvQh7*\/0hNل3C. (h"uP397A4ިC>uϑ~Giu+~O~I1$+@wOaTj4>TJhfv6Oz9zaH^ʋX_ur*Є~Ю~Lb8wtpg;DN|/qo(Ct%E'Vi|IJTEbTݓ2OxrNYJmr24J<.OT@)S3@=F!Q }ae65D6&XrM/t$P6`; 3lq]Frx[ZeR@_$D_R=q_RB4w!n M\MUb7 $I `e>Vo`7A.N@V#G(X|wˏ[6@H|=3-՚SmM+/=` 3h/~oھj [m%2===RmVM&{lթxQ^F6Ak Zf~%7ˊC8>pEwXnY%Gk(&c]j_egr2Rhq[tkncM&ZVU +Y#YG:3+:U]T?['ul M5ܠvI;‰x.55PCsM:hK Oxs `5U<^s š.7W?sѽr< UYUi7?并OGsyAL/hyDN?1 1?(f,LuKtyb?9!Kg9u;r]MY.߰a]+6 #m֌YcجȘYr6.ٿ6>hvxŃ4Ok!w]0mR{ڝA7:oiw_uVn0mk:}m)F +Å}FgmzgS ]=G>}99XF#-T") uk2]F6rem=?CI8'Uպ wUUYgr3qTw eխ/|Oww[oֹ޼/uSf 7w{n&cMf|&ugb0t-f( N{0MHYc1,T6["|H0 )lB%)ENEĔm]tGgcaB'a$^o(JJuQS]9!vFJLHP233 >K?,L26Uteum:Ԏ3\2ŕ ,.hC)Uipm\JlR a2q/+eFQ)YȊ`'?:7|&Ω~~RjPx;:Bǔ}|Ȟ>&=Wį ›nMXr_RF=*]'ؔtk"E'TeIOJ$#=52]'cSu4h "dë/+.i4,& 3MWs?<#!mywwuC ztS}?|{3/M0 0 0 0 0 0 0 0 0 0 0 0 8@ob,K'i,hFa s_ Ts5 *A00~,a$ڍ[n[qsaǗ!:z.h#_*'_C|;>u+R <9aj|gqfUj8[ endstream endobj 9 0 obj <> endobj 38 0 obj <>stream x|Tǵ!{VV#4뇫W,]HrB#g!t5dmnDhu[/~Zah)ݾ*!_󺥗n 6_}Xt ?—k-[oWl za!%@9"ʻ]nFwo2t5{Ѓh?FOW'y|GYdtr?`LnHɹ,T΄0cBH)H#^OZ=QJ3Uޟ<|<th!Z Z _V5ZþUQCpSGm@V ]i#-ٷIކC]vh\.=;KP3WD$͹]Z݀n[7Nh 7u+`wK`_FE1^t?zl rCt=E]֨F^V::%:厩Ojk7mTK!3.HW@ry@T]brSr>K̗-,~7 h?y7.4g?7m?G!MTFcb 4PhLW?$NC`!E'|yrOyt{M[?Dπ )z[ϣ+XG q}h1ZhYd ztw͙=}f[kKsScC}]fFuUeEyYiI^nNvF4V`k5jR!FMptpX RX18s =2G<=21y$ը:'; j >77çE)rYTF0gx04|Mp!԰BF4ZZ`#8hJO~v4-]>< yAְaX)^+3>1-떇/]7/M{^?lg3w E^1jlbݓ?!O7:ssJ9OD()⤚`?  {7@`cxOWeQȋsd Ka{&O IU5 J.Y޳, E eC\bomnpHbT֦<8~ b QCWp^h5TO5=})iֆa48$5H+дw V*x}89TQ?a{TJioArϕ>Op8'3_ (e;hv0)2 qd+T_ ;.qh}u{; ~E:s|ɩ `~-y{GU) c|ѣ eV49K7(]m.3T:[.>-8EjFs}PbN)ѵX=}bmKV2-n f\`sêUn'7[vB={CQZZm[\ M[yi( .سlH"wcJrP򽡞jx}{v2v>>'|OH57,;n}G°Xˑ\I6d\6Tc {eb=4by q4O`yh^B#$jP1ۦrR=W' ١*ơ4̅jF0 kB+ꇵz_Kki+0rO;?Շ<"O.<9S[X7Gfq-2gh)GUFچlᐶa5\A-]h!' A@=q}kEsQk^S%?׿*&4Mz"pox`~*I; h[zԩ/xh p b^3΅ ?µI#~z°(Jj#[%>M.5Cg!7-^I Z UGhkJRr蝏x8tY0哓"bs =?cxa<'[u~^޻W/~R@<5@+Pᓚ|Ƀ꿑ScL$@l <SӭP;xTƸkx&+frFv1\ȥlgF1-lbd##Y:F2r1#1Ռbd%#+Y#Y #KY#YFcd>#ed.#=t3Ff32NF:igd&#m2H3#M42H=#u$eT3RH%#3RH)#%3RH!#3H.#9d3g$LF21e$H# 0gLj4F<q1d#VF,11"0bd#ZF4Q1dD#<##$-*t %QQW<OPt,gn}DŇT|@?GsA?R6;W*ޢM*ޠ?ѭ?ҭ?ЭTNhTPkzȯ/xe1ˣy ~AK4TH TC'>={ti*NP]*ߡ *Sq1zQ8G8LšQ{-QB#T SqǨ6RqGFUIt~*Aש_!*zUB}tߗ{=tn*Nz۩[7Sq=rKōT@T\7j[ Q2Pqm%r bϨ 1bV b7wvRcԶeKN%Tlb+[77Qq6bzz:*Rq1QUVWP9D2*R1H*B;[DBZOow^zTPMEר5bΨQ+1Y֫AtZs@tCک9jѭV*Zhfu7Q GWhQ?jnQGEZ*jF|3VD&bTZ@@((5e(GHGMmQKOϡME^,Lz *bTDT55bz?>z4* Cއރ}; ނaO?!ux 7_~b+ _I"qS3:OH?Яsi@b|?.I&wtOG!qwQ`pP{1j/?k9|P{ >_k ׺%"n];wnnݪE3*͚oo<쿖WrU{z<{wW{9^7' ͮ;转w{C+kս+fݶu6|`n܆am񺭽{܋6ټgfY7sh3֌M8kصY/4oл+^7|UzW/]q`yPޥ僽Kz]Tw}ys{{)>;|V,,o8;@koKyso i4^ 70+ yp}'yG<Þlt\хf[\K83sYfd;o#ewmem#%bY;hц6k02nz۞8F.aÍ#_>a((k6z|My{B91ݜF_jgk9oF<`W63Cv,<Pwja|p|' +nF `5Y_qڛoFaoO=@LA;/޲mK[Y}D*MpנՀW\  p)`;6V&Fz:Zŀk++CeAb``!`]9ـYN@0hMF@PHj5j@P(J%b@Pr9l@db( Bt@> p @h(  o0p08 81#=wo8 ீ xg^Uo+/^/<xp 3O?#3~8 >{'O xc1Q#ÀCQ`pۀG&a~7_| UC|pˀ{"n];wnp 7npZnch?ch?ch?ch?|`|`|`|`|`|`|`|`h?ch>ch>ch~K#9B-rUN4 -҃IQ%>rبQ~̕C0x¸!aqnwmhfõʛ׎6lkyqޫ»Ϛ*~ )ha5pJUJJbҢ8J7pb^qiY _Tx+˩6_<=vj}nUsiNsNuDY*yek4ymvY2{6I93 gUj4*NP`GG )N`$_zr+e% -m oilrp698}4qp-M#As(I(?8囇DrBBӺc(KW֎(ӵV༁ߋJ+|)N dRY(-1A{6b>reʰ|ЦcLns*YԔw/9z5+rq׳T5Dkl쪘?{ܹ-fMIzu%BU_'ʺFK'ޑ>h#Zww!4 'CA٣8 |;M8_xdA~jP4KMj۬>LUĒmzKg/\Q~тfJTZpn^^V2t-]FFf53wكl,6[,X^麧w|h^TaA $Vv X6-r,r,V( 8' 7Ս[ҍ[d1nI7' Unt.ȩ0],bxsLBb;?7ux# oF7_{5GyTiJeKF1Fc]ǤIw:6ƙj%` ͻǰ*'(F.2QLZP<э}CAy%Uwr+Uz\_IUkJ=f-챚=&U"f1e@e 厡E#JTnTnTnTnTn ދ|^%RC]. 'RISd Þ6\(2 S͋<t ,枴A)ZfRr9|#J%́D;\[C:P:P:P:P:P:RiXXB@ „| &@9P q0uXwLt-?Q)SL*'UO Q5tC\DW*kNQ{*QNՌqٯS0.lhZlA$"IHR!T$Њ5'&4BX\(dӍ|0ݷtRv])'wߎnDŽ;P \,drG䒷3uHHEHEHEHEcbA"Z0j<i I HlVcHiMd|k?Q(d~֤L#G!h/lSV4W)erл-mһQ1dIIIIuHm춍Hq)Vo)sP=~ґ9YInXcz!)M|E|a5z4! lJ䇝j]ӺQ:Ǣjܩ(y3?+sgx\Zk|n @VI4JR/w222}BB|08" _y&3X>O.H2)h!6|(bUz[_掅B@]q*Uno5Joia#wfUz2Zoa{ֻgdky$#]xhp ow!·88 iٛ ڕp[Ġ$ԲPj*J(_;>I>R}R8Q\j g{Ber 'bĕޜykw}3|[^Hl6nҒ/nt Y2%or߬7=j}so.3>/ eKG )& &0yzD=^A^aÚC =dҥ)@s#,%Ilw-A*Ynl\#He4?؆8&.^~uwQ՚wV[2WhڼƁ9ž_S/^B{ ۽fezFW6lVUAQMct-ZbxZͯΪ.,ѳ t3usK~&N!0W+*qd|6a@ ^wX;boLeJXe = `V 8@L'@"T”KCvvvvv@z%FY$p M[Lٍ`|Df]eM{ƶ] @0;'Q`S4[alֈ/-hU8^^a y}!ˣLy8D+홓Jt 3?Ui nP>Q73gG8fgv&o)u@L >c<9R"bz93=ieדu/5xiN)5 lVƒL2]r6ʡ qVymzZ(UzX? 񉱝eGiN$td&Q-T>娦 OYGQiieҒhЦJޮcA_Įr9G0Ù\?LN6V*kRm2^dkUŦ2|Ơ$fd<=k@>c>ת:(Q1gĕ }!PdB*YT T,sU'1*ŹuYcؓ0>e޷rgShi8x'*BXC uJR)ƓrdS҇Uwv(#Ͻ'uK!Y>jHGZ<;H!NgE&O1OL]Qf2 S8qE: S?;>2xߴe IqJ&-+Ci{f y̎ҿ6l-xu,ˆ?\ʎ?Ldr@~Kc‚+ΝV&i:h4hT3יۖ_6o(nmΎ3g\rRm3V޸xk'>]u\R}Zɸ|_Br\R\( #rBIMEE,бK?]@RT<9=xUUqιqFo2ɬܚ:h;ݕՖ\0N W = HuOp1Ϟ DZyF[Z5q0-gB &sMRArkη̸ 鬟8'NnN}tÚS%%Zz3!V$u3ksr:\):S!K*$7$e~I=jXSWjQYs+4Z܊UaNsؽ㖶|!%<6 Uc?_ ϫyuYp5XLi /qt~-}ƊYi= )k?GGy,%493\6z5L%x<ӤZVYs;Ƈ?h.myF6k &NsBг ]^{m+S&?&E#S&Eۄ(sĤ EE&>s .ѐHJCQ^ZiiдӉߐYÙ7ic2& PʄT,Nr-jV|FF&ʳ =ĜޮD,{gw2Ӧ!:(myYL[F'ÆP5@ x̡H8ßW]-[g :]0eb%깤.osdFhLd H:ϑ"GAHVCPz$VR}]4zu$ړM?p0 pTB 3Ѽ߉9K>_ K>+e\oȢ%eNc z>@gE&5e*3yrwtܟ:ϩD%Ǹ݄^;Z=̀r\Fd$G8Q?pԋci8C3y\Y*qU& w  +F)HqHumqDlap f{Pi5g}k {\::Dɿ 8Y[{ 4I=5uL'*Z1g>LkF)T~L;2|,zwr.if+{Sf _Ԗ%բ*Y2UEFR[҃%UlSiH}eBhCC'~#x\{|9C vejbYJΩF6X2^Q&GlY(p'!|`yv⨡Mɕn*'saKciӴfvJfђiQ,drxr"حJREA;`|J%}tZ1”H #Ip̬ٜ92s-Z9<'Pkx zyfTHCK.ne- t\oqYL ]uݮC{87R [xB!Hćf.A1nQ/=Gc+=U{W~)h +-)9cҫirzܯutVwufYkebi.$,?6\i4FBj񝣉wЄRj"#c]&_0%_|tkJOxyşͯAB}bry &K,cev[t|iwy4#M~䂟LZ9PWW7m^\%S(= U;z(!3RMrgfqV;NDT2^j.)bQqi77ʻJymv{Xh2NHsL*n6ε_RRprI+/4pw ٩l;_Z@< d{v;XZQpӅpc%b;C#Uա]3+q9͋K3#,OzOhҬp0FF!s ,7l Bٹ~7&dʔ:iMKؖ'DTВw_+۠EGS)gC8]it.ҡΠM&{ωjܽ3m!=U8ͱ۸lvUן= K'p/aqUT7w J 2@ 7t{S/ ȋDže ׉gQWpM,//\@pG]hQkLJɍi'Щ˼hoJL3ʲ=U8c2>mY%&Q w\D8a/8Vg7>i;#Z)fJ ͔F2%fJL$'9[kH]vBzTgv_C @eiDe p R@~1$5i 2ZCd+o6? Kz@Gāq,i4 HY UdENȫ¢J&LU*t k6:vuI󨿗|Lћ+ԋ) U*Ok>rqݦJJ꒞ =uR*5m1wqWIҎB wcݐXpœ@͂ sr[Vټ~z@$^[X֗HaDYF[?=vd@=2cMWS!s\t&QI%ʩx$si)_e!n5K'Q_/Xn7ْqɅa1M&s9YEmBC_+I[-n< } JELJeS"/U12@U.2 7^QNqH|CzW.YȒ2,%#C]~ rtNR99mUZlnh6޿ȟ_y_9sއ\7{yIղH/ }f,%=G>M:4C&=%H:mNLW޾RJ2? tIߛLO&ɼ3$YnϦ۶sϦO!HghrVMIiS2K^H҅4m:9֘2%=}f!]Km_=ϓ^~:tsHsL~5HlB. B. B. B. B. B$#sҊxQF F߄9샽| o2mFlDh+ G,(53iZC~>ߋd(>~~/无4~7oɿߍV- UG >1ߘ|ö w5 )k,ۼApry?s7ALA Sρ|m,@i7ؗωoO)p7#%,C zT@Cd[2}SeiFT#(]C3·,Z /Тbt -ߧ{?,+>* endstream endobj 11 0 obj <> endobj 39 0 obj <>stream x |Tչ{dY2IH2 7ɐdBB HB@,*(+4Zn. ЪUZK[]mZmK}~@Z_^w=;9^`@ ;ͭ9 /ii׆r!:g}Ħk61>ܸf^w/z:OVPY܇ ",m< ^XʹΗ7twڧnσ|yA*/{6n8Y{c1ߝp9\ {Ix V% O<&7{$`O܋2&ً֜%}J=CޘnbLbV;?2'c'J+.k>}ӆ ΂04"Mz@E alDM@?p5T>6pyv/S<.Cϗ. _Aa|^WOL-n@Y7 v/_Jwױi|)vB˻1z;ÖocL= O`= 柆78 oS,C8E>,y͔ENzBt?#^,i\܅qimy싷t))ͩފNt,hמw}n {Ùy&d!<{(p#X:U46? Q$<%wᰠ{sOk 9܅< Ë/˸k ވG1!~/'b #枂Ep~ go_je¡`[뒖͋66- TWWV+;(gvvVzZj7e3uZR!I%b2v#iQ./{;Qy#FUtC0sOe~OY2:w9gg^wH=,k aoMB^&Xx;`qGw R{NpU*=,U(1\$ݻyI` 3ʂL_6¥:#[BtP-TGB_ hS{tçvwENl4wEH&mrO$[Y㒩 0qpOt5TGg[rOdž#x\1Xl Q QyjkvNL5z t";W/Xpixv {kjom3Fssоob-P$ǻ9bV*m M"tt[Er5܁ ߗ%t bG ݎ}Pa~K5NJZ`8qu81>{!'PO%.q/({;zҘsib\-Tk* NPgb0iW[i`K8iuCr$NNK1u>whd(9m:_[鬛Rq墎n?6wCo؋1_0Ɩe!aQ6DT' l5`19ByP*֝Q]?Yy[ν+oZVyEf-nN[\=<otw{[CaKBKil½jn3[⻴{w[(2luGUx4B~AZ^|i d`P+BkA'15ƒN7cQ'"_N]mO0S?&x+ z+FV(=UWJKx0~O>C]bc0qg*"}Y3jA=<,SvL=ET:~.MsXqJIͧ0qq).@~b8-̨cE1v+ἨS8pN91D$s.?,Gl!l&l:!66PIkIUhR5b C&tQԠAu+D;aa9a!L",% m%bB3aQ4DFBPGX@%5QG=:h@TQG#Pu,D#Z eg):+& B>#r Y5QL fe!.,=7Ep G4@lTg%XHi&F3QIKАRMPA/FȢ ! "2`b I*}J8A1τ?EmFmm?> >Gx!L~K T+/ o~A&?'E7 o^Z"~Fx-j= *᧤ ǤB0J"4-Cd aM}^R~pn w$A=j^pk܅%jF5 5"n"|p#Nĵ5U+= 0Y~LvGA.r2¥dy r15p!a;mQ3Vys C4A]o!l&l"l$l 'M5#z=QQDWķ[MΨɏ *R.DGM VDM!GfENDKF|3L$j<5⃝YLhQ/jMl$4PGX5s%)kQDUT/Q}Èʨ~0/磵00PQ}$/CzBtB~T{0!̦dhH>R&!NEH#R^jL9 IdHpP`#K+B4L4N#]@S;AKd2kG(yT !#H ,Edɑ%0ǐ1@D ʧ('P 6FG(jWm}PEGQa(A5ʯPK1 QBX~ Q~ʫ5j\?A11Q^Fy ?@Ey (ϣ|{(>zYuau뻨{QopcO׹Tu=s}kWC9rP5w=pP <Q(DPFC(|兮\)E~Cyvݨ:](w܁r;m(܂r25F (ףENVq-R{P.R]rKRFvw/Tng}dk#ۂ[97x sF!32 1C C! Fпg_47~F1{j_Y_Яn n nػ!tModM;3*],*mi(]\>,. BmH[%d%\(M#Һ`H]pAim07Dw"(GU}SΠMp%Z;Slg6wدsZQedjGoZ߳~kZ,n gV+W$kśV53Z\f9󓺣:Veژk\qiXp~M^IVR),~5jgj.%T6+Y֯έq3 0:'G]Y1ѶVqL[-^avGR[eYDܗ-2UQn$/JJj$"w&#;131@Ҩ¾C>J< ?,1C|+ 4$!V 18Vk_=öj%&W@ sܼ?ےmW0PRXp3{@ 7 P70-5R *_7^?<>~l\wظ,''/{4T*xg%%lQl֛AI+*`K*|'+Ec^˽\I {+qQ rhL*1yͳZOQz?%UHXL"˘S\rN~N*KF,drh׈&jŚ5Vz=WfI&I$;sk=vۨ5TbHeڼWȬ VB!Ur"+$*R``c]QLZ8t^!Cd_[rgJmǘYY &:ILd+kpiV4^iGseeqݸ,P.ѽ2}\˼0_;gFd69قG"Q'"$Ϗ'G$qbB%S/|Ž R :vU8#UZ9sK]-RXxjuTdfݨLN-jq=m]+r̹zji *{S; }Uvoj^XWM_.MhH~-\(gkEz 5}cl\}~{^׽>^G2:[}O1S4k*yfTKbtOWrN"Wi@ԊG$6=[0tdUKK|jq];w[lnlc̖`7TY5޲-nX3l;v\c؟biS;ԖtmwX``Iv[}i'\y>ỷ돤J+GA1A>wVRg~P_-"p/Wl}@_SK4DWNn "Ҵ\ɖpYLSU״]ji\'ޑo:Ü 5gUuW`(t/gWz{6UU.i8J@Y@wB^^[}`>KL=?ČX n:Om9 o|㕘A_mJ =-K[wo|5J5Fƙ8UT/ oEryE]wؙ0(I-2y,I)΢k֬sg봧$kW[< X7@T“]= ,nV-*2hr?Ilsf`TzDO{~nWQ$\V#=dY(LsN̺({TԒ۸oaEQv f'a0kܺC~Oce0Ps͵W]e̶3RT,Ձ%lݹ|ug0nU8܁c/UNd挱j'JJ2z*՛~gnzCY+7Xq {%ZMFW"M+-Jy 6W_'wm6rL-Sk_β/=mC,nT]{e G:ŨV)*QzA"2{aOiBv9z2vyOFȀuӽH1v_p9&W(ŮcSyi\/N^ք^yo[|sb}b3)%RğYcbvF#G/fD/$Y kZbb].~'SD"Q+d27!mR&w džNd1ʸ;U ։щTq3Lsĥ2//3[j)|+ \C̽']O2$BRjuC>=iĚ\o[Wsx#A7̧AὟRՂ#e2iJ/]oI&C+b<ʆYz*pN UH]:i*F.C7p鞌eb\"EgAC=8h/=g B#p4-ŜXq$2uyg_$IG7%h*&\l ߿ٸGߑ(r'zvVl[梒5-iUˤDxkO.Y2^ؼpe-i ʳJnm&ę^1vYyC%ӫdŠtrOf/_u`Q*xOo>#z0|FegJ|U2|ϗ[b-BnU]rY/>OqcgjE)+drN5чa.zDHrcc\ƿ J&#gXBG$:ғ,2\%sgXK:XٮTITF>FiְJ^10 r Rv9D UIn96jRݖcR\$,98>cyy <<_..wg}5O=E7ÇLxYD ^1.Q&VztMe5evt&f6J$JU('v{=OO.l:>rBi3/4o !I5zy-cAi,}Q>~i?퓍-c$2%GZ*[d%&դ2F+~ak%~lDS 6?#3,$h{k_FUcP w7T+}*O. _Fo)<#32#32#3A~o<|h#Gc\Mxx&' O>0;T.|񟂑@ endstream endobj 13 0 obj <> endobj 40 0 obj <>stream x \\}ofcfaYfXfؗ [XB$!&$dS jZ$j]mITbD[Z۴3$ѺW~.s PB5z2i y;1z \\ʩ7,>cG Qjrx+u,lUI] ְBxŠk7w'4b骮;6tzBtݱzY *\]kb|UKYn_HB F&>@$Gȓw$"83y|Lʩd?t5O12vb}cNlQЌ 6:4LEtbYh\18݋%˷qRsI%FKd3 l!K2r9J Wd\K#דȍ&r3Vv׉,r79E!B`/A?,#Ov=3cC y'OguLsN>Mgȳ9+<ArH^A)όkX7ek+uy!QiB ϛ\@csrb>Xa({!3ʑ/1]'zFя{;wvfq{}'% V{1~lRl\˾ rO:aQ'YI6 hNX8 yY'OP22,5C4'> ߿H&#qwXO>!B9ӵj>O9L2BFDŽRQNMhEP)BTITCC@srjn-U[1P^ eʴT2T |IATD.| GB4>QޱW\^fZD)J}r.Jfru0ˇtdIKԾcQB|K7./}.;TV3w'uց4>ɚF}F-⸙ =xOmBrِ@@Ќq+Ybjq,`R)6ϺQ%ִTHxgeehfP7BGXػ} +fH/G;|2.k@{6eohKƎ f[MH6iaESK,0>[M6k7/ka^|Gq6b))Yk3g[@at.1 ~bYmfe厪 !KO5(5@ P|Ckq6lG*XigsұAm#ͨ1AւFvHl%:Jj(q.Ei $-ޡ(} 7T?^fSRꐷ`ؖ@xΧ9'2PIU-ʲ>ɪi"s`eakCO˫@cak*PY`w44v}m'-^l`^ؤeTo+-5TFT h+D3NPpD%/_;qC[FOp|a"D96n ~o q]T?!>ŴO01㈏ÜÈQ}1{wEqoV?!Džo<o"@Y^"x{a/#~ %ċ؈C>9x,ӈO"@x "#B<؃؍#b?6 K;fC܋A܍ q';;"noF܄oD܀qZ,w bjW!D\Uo#.C .E\ .F\)' l~f>ys59nD?&p6b5b,ę3K%D;b1 ъXXXhG^D1рG! j5jD1 Q(G!J%Q(B@"#! Q|D"Fd!2td)md-ě7DU V{0wb ^B88x~+lsgy#KObeO G./#v"~ou7܃o77~771mefَYnŴ[0 sވ \o\ůAlC\M s^ohlŜ#.C ##Z##Z##~i?b ]rG#9@yq<d  r w s;@n dv M 7r=u ׂ\ j\Xa Tp_q'oz_M3zMswnJ6El+{7\UuަޣMK{^{;{ƞzW^E@:GzmЊ=5;{n=H{h}O{v$$U9=1?۽[յkG]]Wvq+W{^M~n@k7J(Y`3+gxW<ûܽԻlRo{]nl.r/.ܹn·M^&o;wg=;5jwjgrWx\ A~f=;;w<=m6Qm+cx-\8D[+ZoxuwX׭szAos+;|v#VKKw>R(_8+׆8BZE#hBXSPAά4 :b5CM3#嘒bL)(ᩕRBu>,0wGR)`SU3$[ _裗*4,.̓^2H&_Y_u+)56nkÍn FWۚ5kָֺҶ4k{G+w-KY@7|X5 b5{HQbmboG|cO~o>'jq2]Jx"'!MJd}aOYYH1rJ_ ![p 19}Urp9V9D=o2yV_>")XUǗ$pm30ZCBxYȲjkjI1RIsK/*cXSKC/)r?^AsQlFI!& 3j4Z4dC)#78J`u9FŶ"ۙl6-cToSY7UL"rwgdۣ (f/tADcj].0p gza`F&#L/9,X|ai\gik9l|]FK]yIGW͸h[AYZdyڂ[˫ɳПw+J OLHMLj8XSf֝IN,J<#_JʘV}a z4HJ~AA+B'=T@W VcLtf5K31ӬIP2\$fR?vL-upH'>N"!f*ItѰFhV; yf8M{s IZ Caեۏx;oZk;.Ygw0r>:Zwlj~ks-g̪M?_x}+ϻ z V02cI2^&qۈqO wtrLG4۵G04E[=<΄> ;mOL~Ɨ]h I4ݸv}SpzEmrbon,{vrGn,ZyIYsj*~7Zy.)#bd>Yqw?X/~ۮ)[30l F/0^VP&e Ni44##i3 Z6<-3%3N-YkHR .4o&e%*GVxV)jj˘3>nS%*wڙg5&Tǜv~&̔QfЬc:$4-W{Hb"6ĕ :=oqHMʦlPk`}vL#`:O_k-Z/;"qQ:Zw]l qTPJH'8A.ne>Zn=t#H[#zΜˏY9HĵL+BdVfn.•:o36Y?_83svNWɔm]W^۞yyѳsZܖP\ 5QrΚܔ┈ђg7'{/^ZXB-_f+q?$>ƭ%$q$Lp,j#d%U*Z* {AQ+.z#îb3oc]٤5TfxYp6^*V=}ƎUy\T[:32sɊڬ|FK|1((s6=fʳEiJasAj=ӵkL6Xc<\ U MДjJPDU咽{19y2o<2*lMV_h֖%W/TKw8c'r;s3f ae1YV\HZUgܺww韕:L)G*3.?1SV v{ɦRp[*w2WdYƧrԧ%l5Htnv]&I8$٭x:ABuUDi" 2(bup`nkeà->[|9Ip C #,YZUCxN`m?.N wjApc<iԆF[E%Yܘ0;Y6w)r>^Ut5o<;Hi@AgC{>Eae5d GJhɡjBu;+$[,!OVUoij KpohI nGFYLi Ƀ+s ^49z311;"u+#ó;.mr1ó5mޞm'eO[rܔZ5 W9aŻc,e G9]PMBd m%2[a^Xޑh_R5\oR:Ee}RV72/-ۭf]faN/KI&Yܑ̔!}9%zVPi ѳq qp'o\?mŵeulF##VPL_8u3T-쫍WjR)\Ꜹґ]A\FÅu,8l΁ӈO㰑6pp:suUWӾWlNmyxQw oSxMBK鳧W͞^^)`%';!nn9S~s(q8&_S=X+ 3*fOx69铝 Veornį 2:6LS9E`f9}|n{PP$[)FeL}RmMMb˦a9})t ^z*J /-heb͜FϒI'ɥѰ3gg/ZܖETVp`LQ{}ʹܤJ2'qj"IViQzWMmک5X )@`(=$`>2n쬔!0CJLS&(??VcFIp(!r}BaӧHWL+jC j1 _gr22զ!L'j橔T>O` A5yHm!-E0QPxtI\cYIuȏ:?jx<[]Va-i4M][6qp Xq+3VG%!j%xss#3jjg82۶4 !C΂LYTPWk$jQ8Am I1‚b)0VkMrC!4aIR;Ʊ+$dن^zXLO&4v5j҂33 ΰqB /<`ĥ-k$@{IW{ \q+_%0#d;ూBf֜]Vxg-OGXrJ&ݔ Mn\'/.ɨ|T S91).3ZU%WFv柅7YJð[,hӪU誄fc+/CK;NlU?7o{-h(x]Wk;S:)7~{mť˹qhHw'nDTDWIt3FVM(f4>p+XࣧdHE fa~!dqRrbP]~zPP1T7#Sa*L0T Sa*L0T Sa*L0T1׸_c j"#fZ$u&z91Ag>5K)GzWt%5DB_rFȱ1RvB mav"$B_a"9lot%>")v)AB*HjHI"'@ مZ|T{d3HwYbڹqJdJdJ)Ιag1A߮Gk ?#xxyF*>?y> endstream endobj 2 0 obj <>endobj xref 0 52 0000000000 65535 f 0000011351 00000 n 0000077662 00000 n 0000011269 00000 n 0000010785 00000 n 0000000015 00000 n 0000004038 00000 n 0000011399 00000 n 0000014369 00000 n 0000041362 00000 n 0000015575 00000 n 0000060953 00000 n 0000016301 00000 n 0000068519 00000 n 0000011785 00000 n 0000016740 00000 n 0000012019 00000 n 0000020003 00000 n 0000012784 00000 n 0000024853 00000 n 0000013486 00000 n 0000036206 00000 n 0000011440 00000 n 0000011470 00000 n 0000010945 00000 n 0000004058 00000 n 0000008031 00000 n 0000011566 00000 n 0000011596 00000 n 0000011107 00000 n 0000008052 00000 n 0000010764 00000 n 0000011681 00000 n 0000011711 00000 n 0000016938 00000 n 0000020199 00000 n 0000025054 00000 n 0000036426 00000 n 0000041564 00000 n 0000061158 00000 n 0000068725 00000 n 0000011932 00000 n 0000012165 00000 n 0000012251 00000 n 0000013159 00000 n 0000013637 00000 n 0000013719 00000 n 0000014829 00000 n 0000015277 00000 n 0000015800 00000 n 0000015946 00000 n 0000016556 00000 n trailer << /Size 52 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 77891 %%EOF HM-HM-18.0/source/App/utils/BitrateTargeting/RuntimeError.h000066400000000000000000000060651442026013100234750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __RUNTIMEERROR__ #define __RUNTIMEERROR__ #include #include /// This class serves the same purpose as std::runtime_error, but it can be more convenient to use class RuntimeError: public std::runtime_error { public: RuntimeError( ): std::runtime_error( "" ), m_firstWhat( true ) { } virtual ~RuntimeError( ) throw ( ) { } /// Implementation of the std::exception::what method const char * what( ) const throw( ) { if( m_firstWhat ) { std::ostringstream o; outputWhat( o ); m_what = o.str( ); m_firstWhat = false; } return m_what.c_str( ); } protected: /// The implementing class implements this method to customize the what output /// \param o The what stream is outputted to this parameter virtual void outputWhat( std::ostream & o ) const =0; private: mutable bool m_firstWhat; ///< True i.f.f. the what method has not yet been called mutable std::string m_what; ///< Contains the what string. Populated by the first call to the what method. }; /// Convenient formatted output operator that just outputs the what string inline std::ostream& operator<<( std::ostream& left, const RuntimeError& right ) { return left << right.what( ); } #endif HM-HM-18.0/source/App/utils/BitrateTargeting/encode.shl000066400000000000000000000140121442026013100226230ustar00rootroot00000000000000# The copyright in this software is being made available under the BSD # License, included below. This software may be subject to other third party # and contributor rights, including patent rights, and no such rights are # granted under this license. # # Copyright (c) 2010-2022, ITU/ISO/IEC # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the ITU/ISO/IEC nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. # This files contains shell code that is common to both encodeCommand.sh and targetBitrates.sh. # Run this function to validate a "-option value" pair of arguments function checkDollarTwo { if [[ "" == $2 ]] ; then printf "An argument must follow $1.\n" >&2 outputUsageAndExit fi } # If the second argument is empty (not provided), output an error message and the usage, and then exit function verifyProvided { if [[ "" == $2 ]] ; then printf "The $1 parameter must be provided.\n" >&2 outputUsageAndExit fi } function verifyNotDirectory { if [[ `printf "$2\n" | grep '/$'` != "" ]] ; then printf "The $1 parameter cannot be a directory.\n" >&2 outputUsageAndExit fi } function verifyDirectory { if [[ "" == `printf "$2\n" | grep '/$'` ]] ; then printf "The $1 parameter must be a directory.\n" >&2 outputUsageAndExit fi } function verifyConfigurationIdentifier { case $configurationIdentifier in ldLC) ;; raLC) ;; inLC) ;; ldHE) ;; raHE) ;; inHE) ;; *) printf "The provided $CONFIGURATION_IDENTIFIER_STRING is invalid. It must be \"ldLC\", \"raLC\", \"inLC\", \"ldHE\", \"raHE\", or \"inHE\".\n" >&2 outputUsageAndExit ;; esac } function verifyQ { case $1 in 22) ;; 27) ;; 32) ;; 37) ;; *) printf "The provided $Q_STRING, \"$1\", is invalid. It must be \"22\", \"27\", \"32\", or \"37\".\n" >&2 outputUsageAndExit ;; esac } Q_OPTION="-q" EXECUTABLE_OPTION="-e" CONFIGURATION_IDENTIFIER_OPTION="-ci" OUTPUT_DIRECTORY_OPTION="-o" EXTRA_ARGUMENTS_OPTION="-ea" CONFIGURATION_PATH_OPTION="-cp" CONFIGURATION_DIRECTORY_OPTION="-cd" Q_STRING="q ($Q_OPTION)" CONFIGURATION_IDENTIFIER_STRING="configuration identifier ($CONFIGURATION_IDENTIFIER_OPTION)" INPUT_NAME_STRING="input name" OUTPUT_DIRECTORY_STRING="output directory ($OUTPUT_DIRECTORY_OPTION)" USAGE_INDENT=" " INPUT_NAME_USAGE_STRING=inputName CONFIGURATION_IDENTIFIER_USAGE_STRING=configurationIdentifier Q_USAGE_STRING=q OUTPUT_DIRECTORY_USAGE_STRING=outputDirectory EXTRA_ARGUMENTS_USAGE_STRING=extraArguments function outputConfigurationIdentifierUsage { echo "${USAGE_INDENT}$CONFIGURATION_IDENTIFIER_USAGE_STRING specifies the configuration (ldHE, ldLC, raHE, raLC, inHE, or inLC)." >&2 } function outputQUsage { echo "${USAGE_INDENT}$Q_USAGE_STRING is the QP value (22, 27, 32, or 37)." >&2 } function outputOutputDirectoryUsage { echo "${USAGE_INDENT}$OUTPUT_DIRECTORY_USAGE_STRING is the directory that will contain the output log, YUV, and bin." >&2 } function outputInputNameUsage { echo "${USAGE_INDENT}$INPUT_NAME_USAGE_STRING is the name of the input sequence. Must be one of the following:" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}NebutaFestival_2560x1600_60_10bit_crop" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}SteamLocomotiveTrain_2560x1600_60_10bit_crop" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}Traffic_2560x1600_30_crop" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}PeopleOnStreet_2560x1600_30_crop" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BQTerrace_1920x1080_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BasketballDrive_1920x1080_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}Cactus_1920x1080_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}Kimono1_1920x1080_24" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}ParkScene_1920x1080_24" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}vidyo1_720p_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}vidyo3_720p_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}vidyo4_720p_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}RaceHorses_832x480_30" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BQMall_832x480_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}PartyScene_832x480_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BasketballDrill_832x480_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}RaceHorses_416x240_30" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BQSquare_416x240_60" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BlowingBubbles_416x240_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BasketballPass_416x240_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}BasketballDrillText_832x480_50" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}Chinaspeed_1024x768_30" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}SlideEditing_1280x720_30" >&2 echo "${USAGE_INDENT}${USAGE_INDENT}SlideShow_1280x720_20" >&2 } HM-HM-18.0/source/App/utils/BitrateTargeting/encodeCommand.sh000066400000000000000000000275331442026013100237620ustar00rootroot00000000000000#! /bin/sh # The copyright in this software is being made available under the BSD # License, included below. This software may be subject to other third party # and contributor rights, including patent rights, and no such rights are # granted under this license. # # Copyright (c) 2010-2022, ITU/ISO/IEC # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the ITU/ISO/IEC nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. # Outputs a command to run the encoder for a given set of arguments. The encoder typically requires a lot of arguments to run, so this script can be more convenient than running the encoder direcly because it automatically generates many of the arguments. # "Include" encode.shl which contains common shell script code related to encoding SUB_TOOLS_DIRECTORY=$(echo "$0" | sed -e 's/[^\/]*$//') . ${SUB_TOOLS_DIRECTORY}encode.shl USE_LOG_FILE_OPTION="-l" INPUT_DIRECTORY_OPTION="-id" NUM_FRAMES_OPTION="-f" function outputUsageAndExit { local EXECUTABLE_USAGE_STRING=executable local INPUT_DIRECTORY_USAGE_STRING=inputDirectory local CONFIGURATION_PATH_USAGE_STRING=configurationPath local CONFIGURATION_DIRECTORY_USAGE_STRING=configurationDirectory local NUM_FRAMES_USAGE_STRING=numFrames echo "Usage: $0 $CONFIGURATION_IDENTIFIER_OPTION $CONFIGURATION_IDENTIFIER_USAGE_STRING ($CONFIGURATION_PATH_OPTION $CONFIGURATION_PATH_USAGE_STRING -or- $CONFIGURATION_DIRECTORY_OPTION $CONFIGURATION_DIRECTORY_USAGE_STRING) $Q_OPTION $Q_USAGE_STRING $EXECUTABLE_OPTION $EXECUTABLE_USAGE_STRING [$NUM_FRAMES_OPTION $NUM_FRAMES_USAGE_STRING] [$EXTRA_ARGUMENTS_OPTION $EXTRA_ARGUMENTS_USAGE_STRING] $OUTPUT_DIRECTORY_OPTION $OUTPUT_DIRECTORY_USAGE_STRING [$USE_LOG_FILE_OPTION] [$INPUT_DIRECTORY_OPTION $INPUT_DIRECTORY_USAGE_STRING] $INPUT_NAME_USAGE_STRING" >&2 outputConfigurationIdentifierUsage echo "${USAGE_INDENT}$CONFIGURATION_PATH_USAGE_STRING is the path of the configuration file to use. Either this or $CONFIGURATION_DIRECTORY_USAGE_STRING must be specified (but not both)." >&2 echo "${USAGE_INDENT}$CONFIGURATION_DIRECTORY_USAGE_STRING is the path of the directory that contains the configuration files. The particular file will be chosen based on $CONFIGURATION_IDENTIFIER_USAGE_STRING. Either this or $CONFIGURATION_PATH_USAGE_STRING must be specified (but not both)." >&2 outputQUsage echo "${USAGE_INDENT}$EXECUTABLE_USAGE_STRING is the path of the encoder executable." >&2 echo "${USAGE_INDENT}$NUM_FRAMES_USAGE_STRING is the number of frames to encode. If omitted, the entire sequence will be encoded." >&2 echo "${USAGE_INDENT}$EXTRA_ARGUMENTS_USAGE_STRING is any extra arguments that should be passed on to the encoder." >&2 outputOutputDirectoryUsage echo "${USAGE_INDENT}If $USE_LOG_FILE_OPTION is specified, the encoder will output to a log file. Otherwise it will output to the standard output." >&2 echo "${USAGE_INDENT}$INPUT_DIRECTORY_USAGE_STRING is the directory that contains the sequences. The default value is the SEQUENCE_DIR environment variable." >&2 outputInputNameUsage exit 1 } # Used to lookup the width, height, number of frames, and frame rate for a given sequence table=`printf "${table}\nNebutaFestival_2560x1600_60_10bit_crop 2560 1600 300 60"` table=`printf "${table}\nSteamLocomotiveTrain_2560x1600_60_10bit_crop 2560 1600 300 60"` table=`printf "${table}\nTraffic_2560x1600_30_crop 2560 1600 150 30"` table=`printf "${table}\nPeopleOnStreet_2560x1600_30_crop 2560 1600 150 30"` table=`printf "${table}\nBQTerrace_1920x1080_60 1920 1080 600 60"` table=`printf "${table}\nBasketballDrive_1920x1080_50 1920 1080 500 50"` table=`printf "${table}\nCactus_1920x1080_50 1920 1080 500 50"` table=`printf "${table}\nKimono1_1920x1080_24 1920 1080 240 24"` table=`printf "${table}\nParkScene_1920x1080_24 1920 1080 240 24"` table=`printf "${table}\nvidyo1_720p_60 1280 720 600 60"` table=`printf "${table}\nvidyo3_720p_60 1280 720 600 60"` table=`printf "${table}\nvidyo4_720p_60 1280 720 600 60"` table=`printf "${table}\nRaceHorses_832x480_30 832 480 300 30"` table=`printf "${table}\nBQMall_832x480_60 832 480 600 60"` table=`printf "${table}\nPartyScene_832x480_50 832 480 500 50"` table=`printf "${table}\nBasketballDrill_832x480_50 832 480 500 50"` table=`printf "${table}\nRaceHorses_416x240_30 416 240 300 30"` table=`printf "${table}\nBQSquare_416x240_60 416 240 600 60"` table=`printf "${table}\nBlowingBubbles_416x240_50 416 240 500 50"` table=`printf "${table}\nBasketballPass_416x240_50 416 240 500 50"` table=`printf "${table}\nBasketballDrillText_832x480_50 832 480 500 50"` table=`printf "${table}\nChinaspeed_1024x768_30 1024 768 500 30"` table=`printf "${table}\nSlideEditing_1280x720_30 1280 720 300 30"` table=`printf "${table}\nSlideShow_1280x720_20 1280 720 500 20"` EXECUTABLE_STRING="executable ($EXECUTABLE_OPTION)" INPUT_DIRECTORY_STRING="input directory ($INPUT_DIRECTORY_OPTION)" CONFIGURATION_PATH_STRING="configuration path ($CONFIGURATION_PATH_OPTION)" CONFIGURATION_DIRECTORY_STRING="configuration directory ($CONFIGURATION_DIRECTORY_OPTION)" inputDirectory="$SEQUENCE_DIR" # The default input directory is taken from this environment variable # For every argument $1 while [ "" != "$*" ] ; do case $1 in $USE_LOG_FILE_OPTION) useLogFile=$1 ;; -*) checkDollarTwo "$1" "$2" case $1 in $EXECUTABLE_OPTION) executable=$2 ;; $INPUT_DIRECTORY_OPTION) inputDirectory=$2 ;; $EXTRA_ARGUMENTS_OPTION) extraArguments=$2 ;; $Q_OPTION) q=$2 ;; $OUTPUT_DIRECTORY_OPTION) outputDirectory=$2 ;; $CONFIGURATION_IDENTIFIER_OPTION) configurationIdentifier=$2 ;; $CONFIGURATION_PATH_OPTION) configurationPath=$2 ;; $CONFIGURATION_DIRECTORY_OPTION) configurationDirectory=$2 ;; $NUM_FRAMES_OPTION) numFrames=$2 ;; *) printf "You entered an invalid option: \"$1\".\n" >&2 outputUsageAndExit ;; esac shift ;; *) if [[ "" == $inputName ]] ; then inputName=$1 else printf "You entered too many arguments.\n" >&2 outputUsageAndExit fi ;; esac shift done verifyProvided "$EXECUTABLE_STRING" "$executable" verifyNotDirectory "$EXECUTABLE_STRING" "$executable" verifyDirectory "$INPUT_DIRECTORY_STRING" "$inputDirectory" verifyProvided "$Q_STRING" "$q" verifyQ $q verifyProvided "$OUTPUT_DIRECTORY_STRING" "$outputDirectory" verifyDirectory "$OUTPUT_DIRECTORY_STRING" "$outputDirectory" verifyProvided "$CONFIGURATION_IDENTIFIER_STRING" "$configurationIdentifier" verifyConfigurationIdentifier "$configurationIdentifier" # Validate $configurationPath or $configurationDirectory if [[ $configurationPath != "" ]] ; then verifyNotDirectory "$CONFIGURATION_PATH_STRING" "$configurationPath" else if [[ "" == $configurationDirectory ]] ; then printf "You must enter a $CONFIGURATION_PATH_STRING or $CONFIGURATION_DIRECTORY_STRING.\n" >&2 outputUsageAndExit else verifyDirectory "$CONFIGURATION_DIRECTORY_STRING" "$configurationDirectory" fi fi verifyProvided "$INPUT_NAME_STRING" "$inputName" verifyNotDirectory "$INPUT_NAME_STRING" "$inputName" # If configurationPath is not already populated, populate it based on the configuration directory and the configuration identifier if [[ "" == $configurationPath ]] ; then configurationPath="${configurationDirectory}encoder_" case $configurationIdentifier in ldLC) configurationPath="${configurationPath}lowdelay_loco" ;; raLC) configurationPath="${configurationPath}randomaccess_loco" ;; inLC) configurationPath="${configurationPath}intra_loco" ;; ldHE) configurationPath="${configurationPath}lowdelay" ;; raHE) configurationPath="${configurationPath}randomaccess" ;; *) configurationPath="${configurationPath}intra" ;; # inHE esac configurationPath="${configurationPath}.cfg" fi # Validate the input name and populate masterLine which contains the line from the table for the given sequence masterLine=`printf "$table" | grep -i "^$inputName "` if [[ "" == $masterLine ]] ; then printf "Invalid input name.\n" >&2 outputUsageAndExit fi # If numFrames is not yet initialized, initialize it by looking up the values in the table if [[ "" == $numFrames ]] ; then numFrames=`printf -- "$masterLine" | awk '{ print $4 }'` fi # Initialize these variables by looking up the values in the table frameRate=`printf -- "$masterLine" | awk '{ print $5 }'` width=`printf -- "$masterLine" | awk '{ print $2 }'` height=`printf -- "$masterLine" | awk '{ print $3 }'` # Initialize intraPeriod case $configurationIdentifier in ld*) intraPeriod="-1" ;; ra*) if [[ 20 == "$frameRate" ]] ; then intraPeriod="16" else intraPeriod=$(expr "$frameRate" + 4) intraPeriod=$(expr "$intraPeriod" / 8) intraPeriod=$(expr "$intraPeriod" \* 8) fi ;; in*) intraPeriod="1" ;; *) outputConfigurationIdentifierErrorAndExit ;; esac # Initialize tenBit if the given sequence is 10-bit printf -- "$inputName" | grep -i '10bit' > /dev/null case $? in 0) tenBit="--InputBitDepth=10 " ;; 1) ;; *) exit $? ;; esac outputPathBegin="${outputDirectory}${inputName}_${configurationIdentifier}_q${q}" # Output the command printf -- "$executable " printf -- "-c $configurationPath " printf -- "-i $inputDirectory$inputName.yuv " printf -- "-f $numFrames " printf -- "-fr $frameRate " printf -- "-wdt $width " printf -- "-hgt $height " printf -- "-ip $intraPeriod " printf -- "$tenBit" if [[ $tenBit != "" ]] ; then printf " " fi printf -- "$extraArguments" if [[ $extraArguments != "" ]] ; then printf -- " " fi printf -- "-q $q " printf -- "-b $outputPathBegin.bin " printf -- "-o $outputPathBegin.yuv " if [[ "" != $useLogFile ]] ; then printf -- "&> $outputPathBegin.log" fi printf "\n" exit 0 HM-HM-18.0/source/App/utils/BitrateTargeting/makefile000066400000000000000000000052511442026013100223630ustar00rootroot00000000000000# The copyright in this software is being made available under the BSD # License, included below. This software may be subject to other third party # and contributor rights, including patent rights, and no such rights are # granted under this license. # # Copyright (c) 2010-2022, ITU/ISO/IEC # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the ITU/ISO/IEC nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. CPPFLAGS = -D NDEBUG -Wall -Wextra extractBitratesObjects = ExtractBitrates.o ExtractBitratesMain.o extractBitratesExecutable = extractBitrates.exe guessLambdaModifiersObjects = GuessLambdaModifiers.o GuessLambdaModifiersMain.o guessLambdaModifiersExecutable = guessLambdaModifiers.exe all: $(extractBitratesExecutable) $(guessLambdaModifiersExecutable) $(extractBitratesExecutable): $(extractBitratesObjects) g++ -o $@ $(extractBitratesObjects) $(guessLambdaModifiersExecutable): $(guessLambdaModifiersObjects) g++ -o $@ $(guessLambdaModifiersObjects) ExtractBitrates.o: ExtractBitrates.h RuntimeError.h ExtractBitratesMain.o: ExtractBitrates.h RuntimeError.h GuessLambdaModifiers.o: GuessLambdaModifiers.h RuntimeError.h GuessLambdaModifiersMain.o: GuessLambdaModifiers.h RuntimeError.h clean: rm $(extractBitratesExecutable) $(extractBitratesObjects) $(guessLambdaModifiersExecutable) $(guessLambdaModifiersObjects) HM-HM-18.0/source/App/utils/BitrateTargeting/targetBitrates.sh000066400000000000000000000417541442026013100242130ustar00rootroot00000000000000#! /bin/sh # The copyright in this software is being made available under the BSD # License, included below. This software may be subject to other third party # and contributor rights, including patent rights, and no such rights are # granted under this license. # # Copyright (c) 2010-2022, ITU/ISO/IEC # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the ITU/ISO/IEC nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. SUB_TOOLS_DIRECTORY=$(echo "$0" | sed -e 's/[^\/]*$//') . ${SUB_TOOLS_DIRECTORY}encode.shl LAMBDA_MODIFIER_PREFIX="LM" RESUME_MODE_OPTION="-rm" TARGET_BITRATES_OPTION="-tb" INITIAL_LAMBDA_MODIFIERS_OPTION="-il" ENCODE_COMMAND_ARGS_OPTION="-ca" function outputUsageAndExit { local TARGET_BITRATES_USAGE_STRING=targetBitrates local INITIAL_LAMBDA_MODIFIERS_USAGE_STRING=initialLambdaModifiers local ENCODE_COMMAND_ARGS_USAGE_STRING=encodeCommandArgs echo "Usage: $0 [$RESUME_MODE_OPTION] $CONFIGURATION_IDENTIFIER_OPTION $CONFIGURATION_IDENTIFIER_USAGE_STRING $Q_OPTION $Q_USAGE_STRING $TARGET_BITRATES_OPTION $TARGET_BITRATES_USAGE_STRING [$INITIAL_LAMBDA_MODIFIERS_OPTION $INITIAL_LAMBDA_MODIFIERS_USAGE_STRING] [$ENCODE_COMMAND_ARGS_OPTION $ENCODE_COMMAND_ARGS_USAGE_STRING] [$EXTRA_ARGUMENTS_OPTION $EXTRA_ARGUMENTS_USAGE_STRING] $OUTPUT_DIRECTORY_OPTION $OUTPUT_DIRECTORY_USAGE_STRING $INPUT_NAME_USAGE_STRING" >&2 echo "${USAGE_INDENT}$RESUME_MODE_OPTION engages resume mode which allows the user to resume an execution that was interrupted before completion." outputConfigurationIdentifierUsage outputQUsage echo "${USAGE_INDENT}$TARGET_BITRATES_USAGE_STRING is the target bitrates. For example: \"23:35 24:3473242 etc...\"." >&2 echo "${USAGE_INDENT}$INITIAL_LAMBDA_MODIFIERS_USAGE_STRING is the Lambda-modifiers to use for the first guess. For example: \"$-{LAMBDA_MODIFIER_PREFIX}23 1e0 $-{LAMBDA_MODIFIER_PREFIX}24 0.98 etc...\"" >&2 echo "${USAGE_INDENT}$ENCODE_COMMAND_ARGS_USAGE_STRING is the extra arguments to be passed to encodeCommand.sh. The common arguments that are available to both $0 and encodeCommand.sh should not be passed though this argument. For example, don't pass $Q_OPTION here because it is an option of $0. $EXECUTABLE_OPTION and ($CONFIGURATION_PATH_OPTION or $CONFIGURATION_DIRECTORY_OPTION) must be passed through this argument. For example, \"$ENCODE_COMMAND_ARGS_OPTION '$EXECUTABLE_OPTION ~/bin/encode.exe $CONFIGURATION_DIRECTORY_OPTION ~/cfg/'\"." >&2 echo "${USAGE_INDENT}$EXTRA_ARGUMENTS_USAGE_STRING specifies extra arguments to be passed directly to the encoder (not to encodeCommand.sh)." >&2 outputOutputDirectoryUsage outputInputNameUsage exit 1 } NORMAL_MODE="NORMAL_MODE" RESUME_MODE="RESUME_MODE" mode="$NORMAL_MODE" # For every argument $1 while [ "" != "$*" ] ; do case $1 in $RESUME_MODE_OPTION) mode="$RESUME_MODE" ;; -*) checkDollarTwo "$1" "$2" case $1 in $EXTRA_ARGUMENTS_OPTION) extraArguments=$2 ;; $Q_OPTION) q=$2 ;; $OUTPUT_DIRECTORY_OPTION) outputDirectory=$2 ;; $CONFIGURATION_IDENTIFIER_OPTION) configurationIdentifier=$2 ;; $TARGET_BITRATES_OPTION) targetBitrates=$2 ;; $INITIAL_LAMBDA_MODIFIERS_OPTION) initialLambdaModifiers=$2 ;; $ENCODE_COMMAND_ARGS_OPTION) encodeCommandArgs=$2 ;; *) printf "You entered an invalid option: \"$1\".\n" >&2 outputUsageAndExit ;; esac shift ;; *) if [[ "" == $inputName ]] ; then inputName=$1 else printf "You entered too many arguments.\n" >&2 outputUsageAndExit fi ;; esac shift done verifyProvided "$Q_STRING" "$q" verifyQ $q verifyProvided "$OUTPUT_DIRECTORY_STRING" "$outputDirectory" verifyDirectory "$OUTPUT_DIRECTORY_STRING" "$outputDirectory" verifyProvided "$CONFIGURATION_IDENTIFIER_STRING" "$configurationIdentifier" verifyConfigurationIdentifier "$configurationIdentifier" verifyProvided "target bitrates ($TARGET_BITRATES_OPTION)" "$targetBitrates" verifyProvided "$INPUT_NAME_STRING" "$inputName" outputPathBegin="${outputDirectory}${inputName}_${configurationIdentifier}_q${q}" logPath="$outputPathBegin.log" metaLogPath="${outputPathBegin}_meta.log" TRUE=true # Outputs "$TRUE" if the given file exist. Outputs nothing if the given file does not exist. The first argument is the path to the supposed file. function doesFileExist { ls $1 &> /dev/null if [[ 0 == "$?" ]] ; then echo "$TRUE" fi } # Validate the mode (normal or resume) based on whether or not the meta-log file already exists if [[ "$TRUE" == "$(doesFileExist "$metaLogPath")" ]] ; then if [[ "$NORMAL_MODE" == "$mode" ]] ; then echo "$metaLogPath already exists. Consider using resume-mode." >&2 outputUsageAndExit else # Resume-mode cat "$metaLogPath" # Output the pre-existing meta-log so we can resume where we left off fi else # Meta-log file does not exist if [[ "$RESUME_MODE" == "$mode" ]] ; then echo "$metaLogPath does not exist and resume-mode is enabled." >&2 outputUsageAndExit fi fi # Outputs the number of elements in the given bitrate vector function bitrateVectorSize { echo "$1" | sed -e 's/[^ ]//g' | wc -c | sed -e 's/^ *//' } # Initialize targetBitrateVectorSize targetBitrateVectorSize="$(bitrateVectorSize "$targetBitrates")" # Outputs the product of the two input values function multiply { echo | awk "{print $1 * $2}" } # Extracts the bitrate at the given index from the given bitrate vector. The first argument is the given index and the second argument in the given bitrate vector. function extractBitrateFromVector { local localIndex=$(expr "$1" "+" "1") echo "$2" | awk "{ print \$$localIndex }" } # Outputs a bitrate vector by multiplying the $targetBitrates vector by a given scalar. The first argument is the given scalar. function populateBitrates { local lI=0 local lResult="" while true ; do local lTargetBitrate=$(extractBitrateFromVector "$lI" "$targetBitrates") if [[ "" == "$lTargetBitrate" ]] ; then break; fi local lNew=$(multiply "$lTargetBitrate" "$1") lResult="$lResult $lNew" ((++lI)) done echo "$lResult" | sed -e 's/^ //' } # Initialize the ranges outerRangeMins=$(populateBitrates "0.980") innerRangeMins=$(populateBitrates "0.985") innerRangeMaxs=$(populateBitrates "1.015") outerRangeMaxs=$(populateBitrates "1.020") # Outputs the given string to the meta-log (both the file and stdout) with no newline character. The first argument is the string to output. function outputToMetaLogNoNewline { toPrint=`echo $1 | sed -e 's/%/%%/g'` printf -- "$toPrint" printf -- "$toPrint" >> $metaLogPath } # Outputs the given string to the meta-log (both the file and stdout) with a newline character. The first argument is the string to output. function outputToMetaLogWithNewline { echo "$1" echo "$1" >> $metaLogPath } # Extracts the Lambda-modifier at the given index from $lambdaModifiers. The first argument is the given index. function extractLambdaModifier { printf -- "$lambdaModifiers" | sed -e 's/^-//' | sed -e 's/ -/\ /g' | grep "${LAMBDA_MODIFIER_PREFIX}$1 " | sed -e 's/^[^ ]* //' } # Outputs the given Lambda-modifier with a fixed number of decimal points. The first argument is the given Lambda-modifier. function formatLambdaModifier { printf "%.7f" "$1" } # Outputs $lambdaModifiers to the meta-log with proper formatting function outputLambdaModifiersToMetaLog { local lI=0 local lLambdaModifier=$(extractLambdaModifier "$lI") local lLambdaModifier=$(formatLambdaModifier "$lLambdaModifier") local lOutput="-${LAMBDA_MODIFIER_PREFIX}$lI $lLambdaModifier" while true ; do ((++lI)) local lLambdaModifier=$(extractLambdaModifier "$lI") if [[ "" == "$lLambdaModifier" ]] ; then break fi local lLambdaModifier=$(formatLambdaModifier "$lLambdaModifier") local lOutput="$lOutput -${LAMBDA_MODIFIER_PREFIX}$lI $lLambdaModifier" done outputToMetaLogNoNewline "$lOutput;" } # Initialize lambdaModifiers and output it to the meta-log if [[ "$RESUME_MODE" == "$mode" ]] ; then if [[ "" == "$initialLambdaModifiers" ]] ; then # If no initial lambda-modifiers provided, use default value lambdaModifiers=$(tail -n 1 < "$metaLogPath" | sed -e 's/;$//') else # Initial lambda-modifiers provided echo "You cannot use $RESUME_MODE and specify the initial lambda-modifiers. In resume-mode, the lambda-modifiers will be retreived from the last line of the meta-log." >&2 outputUsageAndExit fi else if [[ "" == "$initialLambdaModifiers" ]] ; then # If no initial lambda-modifiers provided, use default value lambdaModifiers="-${LAMBDA_MODIFIER_PREFIX}0 1" for (( i=1; i<"$targetBitrateVectorSize"; ++i )); do lambdaModifiers="$lambdaModifiers -${LAMBDA_MODIFIER_PREFIX}${i} 1" done else # Initial lambda-modifiers provided lambdaModifiers="$initialLambdaModifiers" fi outputLambdaModifiersToMetaLog fi # Calculates the difference percentage between the given target bitrate and the given bitrate, appropriately formats this difference percentage, and then outputs it. The first argument is the given target bitrate and the second argument is the given bitrate. function calculateAndFormatDifferencePercentage { # Calculate the result and format it with the right number of decimal places local result=$(echo | awk "{print 100*($2-$1)/$1}") local result=$(printf "%.3f" "$result") # Separate the sign from the result local sign=$(echo "$result" | sed -e 's/[^-]*$//') if [[ "$sign" != "-" ]] ; then local sign="+" fi local result=$(echo "$result" | sed -e 's/^-//') # Pad leading zereos to make two digits before the decimal point if [[ 2 == $(echo "$result" | sed -e 's/\..*$//' | wc -c | sed -e 's/^ *//') ]] ; then local result="0$result" fi # Output the result including the sign and the percent sign echo "${sign}${result}%" } # Outputs $TRUE i.f.f. the first argument is less than the second argument function lessOrEqual { echo | awk "{ if($1 < $2) print \"$TRUE\" }" } # Outputs $TRUE i.f.f. the second argument is greater than the first argument and less than the third argument ($1 < $2 < $3) function isInRange { if [[ "$TRUE" == $(lessOrEqual "$1" "$2") ]] ; then if [[ "$TRUE" == $(lessOrEqual "$2" "$3") ]] ; then echo "$TRUE" fi fi } # From the given bitrate vector, outputs the "bad" bitrates by filtering out the "good" bitrates. The first argument is the index of the last good bitrate and the second argument is the given bitrate vector. If the first argument is -1, then the given bitrate vector is outputted in its entirety. function filterOutGoodBitrates { local result="$2" for (( i=0; i<="$1"; ++i )); do result=$(echo "$result" | sed -e 's/^[^ ]* //') done echo "$result" } # Outputs a given line from the given variable. The first argument is the line number to output and the second argument is the given variable to extract the line from. function outputLine { echo "$2" | head -n "$(expr "$1" + 1)" | tail -n 1 } # Initialize iterationCount if [[ "$RESUME_MODE" == "$mode" ]] ; then iterationCount=$(wc -l < "$metaLogPath" | sed -e 's/^ *//') else iterationCount=0 fi ITERATION_COUNT_LIMIT=50 # The number of attempts to make before giving up while true ; do # The main loop # Run the encoder sh ${SUB_TOOLS_DIRECTORY}encodeCommand.sh $inputName $encodeCommandArgs $CONFIGURATION_IDENTIFIER_OPTION $configurationIdentifier $Q_OPTION $q $OUTPUT_DIRECTORY_OPTION $outputDirectory -ea "$extraArguments $lambdaModifiers" | sh > $logPath if [[ $? != 0 ]] ; then printf "Unexpected exit status from encodeCommand.sh\n" >&2 exit 1 fi # Extract and output the bitrates bitrates=`${SUB_TOOLS_DIRECTORY}extractBitrates.exe < $logPath` outputToMetaLogNoNewline "$bitrates;" # Make sure that the index set of the extracted bitrates matches the index set of the target bitrates if [[ "$targetBitrateVectorSize" != "$(bitrateVectorSize "$bitrates")" ]] ; then echo "Index set from the extracted bitrates does not match the index set from the target bitrates" >&2 exit 1 fi # Calculate the bitrate difference percentages and output them to the meta-log percentages="$(calculateAndFormatDifferencePercentage "$(extractBitrateFromVector "0" "$targetBitrates")" "$(extractBitrateFromVector "0" "$bitrates")")" for (( i=1; i<"$targetBitrateVectorSize"; ++i )); do percentages="$percentages $(calculateAndFormatDifferencePercentage "$(extractBitrateFromVector "$i" "$targetBitrates")" "$(extractBitrateFromVector "$i" "$bitrates")")" done outputToMetaLogNoNewline "$percentages;" # Initialize and output areBitratesSatismodifiery areBitratesSatisfactory=yes for (( i=0; ; ++i )) ; do outerRangeMin=$(extractBitrateFromVector "$i" "$outerRangeMins") bitrate=$(extractBitrateFromVector "$i" "$bitrates") outerRangeMax=$(extractBitrateFromVector "$i" "$outerRangeMaxs") if [[ "" == "$bitrate" ]] ; then break fi if [[ $(isInRange "$outerRangeMin" "$bitrate" "$outerRangeMax") != "$TRUE" ]] ; then areBitratesSatisfactory=no break fi done outputToMetaLogWithNewline "$areBitratesSatisfactory" # Exit if we are finished or if we have iterated too many times if [[ yes == $areBitratesSatisfactory ]] ; then mv "$logPath" "${outputPathBegin}_final.log" exit 0 else # Rename the deprecated log countString="$iterationCount" if [[ 1 == `printf -- "$countString" | wc -c | sed -e 's/^ *//'` ]] ; then countString="0$countString" fi mv "$logPath" "${outputPathBegin}_dep${countString}.log" ((++iterationCount)) if [[ "$ITERATION_COUNT_LIMIT" == "$iterationCount" ]] ; then outputToMetaLogWithNewline "Could not reach target bitrates" exit 1 fi fi filteredMetaLog=$(sed -e 's/;[^;]*$//' < $metaLogPath | sed -e 's/;[^;]*$//') bitratesFromMetaLog=$(printf -- "$filteredMetaLog" | sed -e 's/^[^;]*;//') # Initialize goodIndex goodIndex=-1 for (( i=0; i<"$targetBitrateVectorSize"; ++i )); do innerRangeMin=$(extractBitrateFromVector "$i" "$innerRangeMins") bitrate=$(extractBitrateFromVector "$i" "$bitrates") innerRangeMax=$(extractBitrateFromVector "$i" "$innerRangeMaxs") if [[ "$TRUE" == $(isInRange "$innerRangeMin" "$bitrate" "$innerRangeMax") ]] ; then goodIndex="$i" else break fi done badBitrates=$(filterOutGoodBitrates "$goodIndex" "$bitratesFromMetaLog") lambdaModifiersFromMetaLog=`printf -- "$filteredMetaLog" | sed -e 's/;[^;]*$//'` badLambdaModifiers=`printf -- "$lambdaModifiersFromMetaLog" | sed -e "s/^.*-${LAMBDA_MODIFIER_PREFIX}$goodIndex [^ ]* //"` lineCount=`printf -- "$badBitrates\n" | wc -l | sed -e 's/^ *//'` # Initialize guessLambdaModifiersIn guessLambdaModifiersIn="$(outputLine 0 "$badLambdaModifiers");$(outputLine 0 "$badBitrates")" for (( i=1; i<"$lineCount"; ++i )); do guessLambdaModifiersIn="$(printf -- "$guessLambdaModifiersIn\n$(outputLine "$i" "$badLambdaModifiers");$(outputLine "$i" "$badBitrates")")" done # Run guessLambdaModifiers guessedLambdaModifiers=$(printf -- "$guessLambdaModifiersIn" | ${SUB_TOOLS_DIRECTORY}guessLambdaModifiers.exe "-.5" "$(filterOutGoodBitrates "$goodIndex" "$targetBitrates")") if [[ $? != 0 ]] ; then printf "Unexpected exit status from guessLambdaModifiers.exe\n" >&2 exit 1 fi # Initialize lambdaModifiers and output them to the meta-log lastLambdaModifiersFromMetaLog=`printf -- "$filteredMetaLog" | tail -n 1 | sed -e "s/;[^;]*$//"` goodLambdaModifiersFromMetaLog=`printf -- "$lastLambdaModifiersFromMetaLog" | tail -n 1 | sed -e "s/-${LAMBDA_MODIFIER_PREFIX}$(expr "$goodIndex" + 1).*$//"` lambdaModifiers="${goodLambdaModifiersFromMetaLog}${guessedLambdaModifiers}" outputLambdaModifiersToMetaLog done HM-HM-18.0/source/App/utils/annexBbytecount.cpp000066400000000000000000000224111442026013100212750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "TLibDecoder/AnnexBread.h" using namespace std; static const struct { AnnexBStats expected; unsigned data_len; const char data[10]; } tests[] = { /* trivial cases: startcode, no payload */ {{0, 0, 3, 0, 0}, 3, {0,0,1}}, {{0, 1, 3, 0, 0}, 4, {0,0,0,1}}, {{2, 1, 3, 0, 0}, 6, {0,0,0,0,0,1}}, /* trivial cases: startcode, payload */ {{0, 0, 3, 1, 0}, 4, {0,0,1,2}}, {{0, 0, 3, 2, 0}, 5, {0,0,1,2,0}}, {{0, 0, 3, 3, 0}, 6, {0,0,1,2,0,0}}, {{0, 0, 3, 1, 3}, 7, {0,0,1,2,0,0,0}}, /* trivial cases: two nal units: extract the first */ {{0, 0, 3, 1, 0}, 8, {0,0,1,2,0,0,1,3}}, {{0, 0, 3, 1, 0}, 9, {0,0,1,2,0,0,0,1,3}}, {{0, 0, 3, 1, 1}, 10, {0,0,1,2,0,0,0,0,1,3}}, /* edge cases with EOF near start*/ {{0, 0, 0, 0, 0}, 0, {}}, {{1, 0, 0, 0, 0}, 1, {0}}, {{2, 0, 0, 0, 0}, 2, {0,0}}, {{3, 0, 0, 0, 0}, 3, {0,0,0}}, }; void selftest() { /* test */ for (unsigned i = 0; i < sizeof(tests)/sizeof(*tests); i++) { istringstream in(string(tests[i].data, tests[i].data_len)); InputByteStream bs(in); AnnexBStats actual = AnnexBStats(); vector nalUnit; byteStreamNALUnit(bs, nalUnit, actual); cout << "Self-Test: " << i << ", {"; for (unsigned j = 0; j < tests[i].data_len; j++) { cout << hex << (unsigned int)tests[i].data[j] << dec; if (j < tests[i].data_len-1) { cout << ","; } } cout << "} "; bool ok = true; #define VERIFY(a,b,m) \ if (a.m != b.m) { \ ok = false; \ cout << endl << " MISSMATCH " #m << ", E(" << b.m << ") != " << a.m; \ } VERIFY(actual, tests[i].expected, m_numLeadingZero8BitsBytes); VERIFY(actual, tests[i].expected, m_numZeroByteBytes); VERIFY(actual, tests[i].expected, m_numStartCodePrefixBytes); VERIFY(actual, tests[i].expected, m_numBytesInNALUnit); VERIFY(actual, tests[i].expected, m_numTrailingZero8BitsBytes); #undef VERIFY if (ok) { cout << "OK"; } cout << endl; } } int main(int argc, char*argv[]) { selftest(); if (argc != 2) { return 0; } ifstream in(argv[1], ifstream::in | ifstream::binary); InputByteStream bs(in); AnnexBStats annexBStatsTotal = AnnexBStats(); AnnexBStats annexBStatsTotal_VCL = AnnexBStats(); AnnexBStats annexBStatsTotal_Filler = AnnexBStats(); AnnexBStats annexBStatsTotal_Other = AnnexBStats(); unsigned numNALUnits = 0; cout << "NALUnits:" << endl; while (!!in) { AnnexBStats annexBStatsSingle = AnnexBStats(); vector nalUnit; byteStreamNALUnit(bs, nalUnit, annexBStatsSingle); int nal_unit_type = -1; if (annexBStatsSingle.m_numBytesInNALUnit) { nal_unit_type = nalUnit[0] & 0x1f; } cout << " - NALU: #" << numNALUnits << " nal_unit_type:" << nal_unit_type << endl << " num_bytes(leading_zero_8bits): " << annexBStatsSingle.m_numLeadingZero8BitsBytes << endl << " num_bytes(zero_byte): " << annexBStatsSingle.m_numZeroByteBytes << endl << " num_bytes(start_code_prefix_one_3bytes): " << annexBStatsSingle.m_numStartCodePrefixBytes << endl << " NumBytesInNALunit: " << annexBStatsSingle.m_numBytesInNALUnit << endl << " num_bytes(trailing_zero_8bits): " << annexBStatsSingle.m_numTrailingZero8BitsBytes << endl ; annexBStatsTotal += annexBStatsSingle; numNALUnits++; if (!annexBStatsSingle.m_numBytesInNALUnit) { continue; } /* identify the NAL unit type and add stats to the correct * accumulators */ switch (nalUnit[0] & 0x1f) { case 1: case 2: case 3: case 4: case 5: annexBStatsTotal_VCL += annexBStatsSingle; break; case 12: annexBStatsTotal_Filler += annexBStatsSingle; break; default: annexBStatsTotal_Other += annexBStatsSingle; }; } cout << "Summary: " << endl << " num_bytes(leading_zero_8bits): " << annexBStatsTotal.m_numLeadingZero8BitsBytes << endl << " num_bytes(zero_byte): " << annexBStatsTotal.m_numZeroByteBytes << endl << " num_bytes(start_code_prefix_one_3bytes): " << annexBStatsTotal.m_numStartCodePrefixBytes << endl << " NumBytesInNALunit: " << annexBStatsTotal.m_numBytesInNALUnit << endl << " num_bytes(trailing_zero_8bits): " << annexBStatsTotal.m_numTrailingZero8BitsBytes << endl ; cout << "Summary(VCL): " << endl << " num_bytes(leading_zero_8bits): " << annexBStatsTotal_VCL.m_numLeadingZero8BitsBytes << endl << " num_bytes(zero_byte): " << annexBStatsTotal_VCL.m_numZeroByteBytes << endl << " num_bytes(start_code_prefix_one_3bytes): " << annexBStatsTotal_VCL.m_numStartCodePrefixBytes << endl << " NumBytesInNALunit: " << annexBStatsTotal_VCL.m_numBytesInNALUnit << endl << " num_bytes(trailing_zero_8bits): " << annexBStatsTotal_VCL.m_numTrailingZero8BitsBytes << endl ; cout << "Summary(Filler): " << endl << " num_bytes(leading_zero_8bits): " << annexBStatsTotal_Filler.m_numLeadingZero8BitsBytes << endl << " num_bytes(zero_byte): " << annexBStatsTotal_Filler.m_numZeroByteBytes << endl << " num_bytes(start_code_prefix_one_3bytes): " << annexBStatsTotal_Filler.m_numStartCodePrefixBytes << endl << " NumBytesInNALunit: " << annexBStatsTotal_Filler.m_numBytesInNALUnit << endl << " num_bytes(trailing_zero_8bits): " << annexBStatsTotal_Filler.m_numTrailingZero8BitsBytes << endl ; cout << "Summary(Other): " << endl << " num_bytes(leading_zero_8bits): " << annexBStatsTotal_Other.m_numLeadingZero8BitsBytes << endl << " num_bytes(zero_byte): " << annexBStatsTotal_Other.m_numZeroByteBytes << endl << " num_bytes(start_code_prefix_one_3bytes): " << annexBStatsTotal_Other.m_numStartCodePrefixBytes << endl << " NumBytesInNALunit: " << annexBStatsTotal_Other.m_numBytesInNALUnit << endl << " num_bytes(trailing_zero_8bits): " << annexBStatsTotal_Other.m_numTrailingZero8BitsBytes << endl ; /* The first such type of bitstream, called Type I bitstream, is a * NAL unit stream containing only the VCL NAL units and filler data * NAL units for all access units in the bitstream. */ unsigned totalBytes_T1HRD = annexBStatsTotal_VCL.m_numBytesInNALUnit + annexBStatsTotal_Filler.m_numBytesInNALUnit; /*The second type of bitstream, called a Type II bitstream, * contains, in addition to the VCL NAL units and filler data NAL * units for all access units in the bitstream, at least one of * the following: * (a) additional non-VCL NAL units other than filler data NAL * units. */ unsigned totalBytes_T2aHRD = annexBStatsTotal.m_numBytesInNALUnit; /* (b) all leading_zero_8bits, zero_byte, * start_code_prefix_one_3bytes, and trailing_zero_8bits syntax * elements that form a byte stream from the NAL unit stream (as * specified in Annex B) */ unsigned totalBytes_T2abHRD = 0; totalBytes_T2abHRD += annexBStatsTotal.m_numLeadingZero8BitsBytes; totalBytes_T2abHRD += annexBStatsTotal.m_numZeroByteBytes; totalBytes_T2abHRD += annexBStatsTotal.m_numStartCodePrefixBytes; totalBytes_T2abHRD += annexBStatsTotal.m_numBytesInNALUnit; totalBytes_T2abHRD += annexBStatsTotal.m_numTrailingZero8BitsBytes; cout << "Totals (bytes):" << endl; cout << " Type1 HRD: " << totalBytes_T1HRD << endl; cout << " Type2 HRD: " << totalBytes_T2aHRD << endl; cout << " Type2b HRD: " << totalBytes_T2abHRD << endl; return 0; } HM-HM-18.0/source/App/utils/convert_NtoMbit_YCbCr.cpp000066400000000000000000000116341442026013100222700ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "TLibCommon/TComPicYuv.h" #include "TLibVideoIO/TVideoIOYuv.h" #include "TAppCommon/program_options_lite.h" using namespace std; namespace po = df::program_options_lite; Int main(Int argc, const char** argv) { Bool do_help; string filename_in, filename_out; UInt width, height; UInt bitdepth_in, bitdepth_out, chromaFormatRaw; UInt num_frames; UInt num_frames_skip; po::Options opts; opts.addOptions() ("help", do_help, false, "this help text") ("InputFile,i", filename_in, string(""), "input file to convert") ("OutputFile,o", filename_out, string(""), "output file") ("SourceWidth", width, 0u, "source picture width") ("SourceHeight", height, 0u, "source picture height") ("InputBitDepth", bitdepth_in, 8u, "bit-depth of input file") ("OutputBitDepth", bitdepth_out, 8u, "bit-depth of output file") ("ChromaFormat", chromaFormatRaw, 420u, "chroma format. 400, 420, 422 or 444 only") ("NumFrames", num_frames, 0xffffffffu, "number of frames to process") ("FrameSkip,-fs", num_frames_skip, 0u, "Number of frames to skip at start of input YUV") ; po::setDefaults(opts); po::scanArgv(opts, argc, argv); if (argc == 1 || do_help) { /* argc == 1: no options have been specified */ po::doHelp(cout, opts); return EXIT_FAILURE; } ChromaFormat chromaFormatIDC=CHROMA_420; switch (chromaFormatRaw) { case 400: chromaFormatIDC=CHROMA_400; break; case 420: chromaFormatIDC=CHROMA_420; break; case 422: chromaFormatIDC=CHROMA_422; break; case 444: chromaFormatIDC=CHROMA_444; break; default: fprintf(stderr, "Bad chroma format string\n"); return EXIT_FAILURE; } TVideoIOYuv input; TVideoIOYuv output; Int inputBitDepths [MAX_NUM_CHANNEL_TYPE]; Int outputBitDepths[MAX_NUM_CHANNEL_TYPE]; for (UInt channelTypeIndex = 0; channelTypeIndex < MAX_NUM_CHANNEL_TYPE; channelTypeIndex++) { inputBitDepths [channelTypeIndex] = bitdepth_in; outputBitDepths[channelTypeIndex] = bitdepth_out; } input.open((char*)filename_in.c_str(), false, inputBitDepths, inputBitDepths, outputBitDepths); output.open((char*)filename_out.c_str(), true, outputBitDepths, outputBitDepths, outputBitDepths); input.skipFrames(num_frames_skip, width, height, chromaFormatIDC); TComPicYuv frame; frame.createWithoutCUInfo( width, height, chromaFormatIDC); Int pad[2] = {0, 0}; TComPicYuv cPicYuvTrueOrg; cPicYuvTrueOrg.createWithoutCUInfo( width, height, chromaFormatIDC ); UInt num_frames_processed = 0; while (!input.isEof()) { if (! input.read(&frame, &cPicYuvTrueOrg, IPCOLOURSPACE_UNCHANGED, pad)) { break; } #if 0 Pel* img = frame.getAddr(COMPONENT_Y); for (Int y = 0; y < height; y++) { for (Int x = 0; x < height; x++) { img[x] = 0; } img += frame.getStride(); } img = frame.getAddr(COMPONENT_Y); img[0] = 1; #endif output.write(&frame, IPCOLOURSPACE_UNCHANGED); num_frames_processed++; if (num_frames_processed == num_frames) { break; } } input.close(); output.close(); cPicYuvTrueOrg.destroy(); return EXIT_SUCCESS; } HM-HM-18.0/source/Lib/000077500000000000000000000000001442026013100142475ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibCommon/000077500000000000000000000000001442026013100162525ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibCommon/AccessUnit.h000066400000000000000000000053411442026013100204670ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file AccessUnit.h \brief Access Unit class (header) */ #pragma once #ifndef __ACCESSUNIT__ #define __ACCESSUNIT__ #include #include "NAL.h" //! \ingroup TLibCommon //! \{ /** * An AccessUnit is a list of one or more NAL units, according to the * working draft. All NAL units within the object belong to the same * access unit. * * NALUnits held in the AccessUnit list are in EBSP format. Attempting * to insert an OutputNALUnit into the access unit will automatically cause * the nalunit to have its headers written and anti-emulation performed. * * The AccessUnit owns all pointers stored within. Destroying the * AccessUnit will delete all contained objects. */ class AccessUnit : public std::list // NOTE: Should not inherit from STL. { public: ~AccessUnit() { for (AccessUnit::iterator it = this->begin(); it != this->end(); it++) { delete *it; } } }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/CMakeLists.txt000066400000000000000000000055141442026013100210170ustar00rootroot00000000000000# library set( LIB_NAME TLibCommon ) # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # get source files file( GLOB BASE_SRC_FILES "*.cpp" ) # get include files file( GLOB BASE_INC_FILES "*.h" ) # get x86 source files file( GLOB X86_SRC_FILES "x86/*.cpp" ) # get x86 include files file( GLOB X86_INC_FILES "x86/*.h" ) # get avx source files file( GLOB AVX_SRC_FILES "x86/avx/*.cpp" ) # get avx2 source files file( GLOB AVX2_SRC_FILES "x86/avx2/*.cpp" ) # get sse4.2 source files file( GLOB SSE42_SRC_FILES "x86/sse42/*.cpp" ) # get sse4.1 source files file( GLOB SSE41_SRC_FILES "x86/sse41/*.cpp" ) # get libmd5 source files file( GLOB MD5_SRC_FILES "../libmd5/*.cpp" ) # get libmd5 include files file( GLOB MD5_INC_FILES "../libmd5/*.h" ) # get all source files set( SRC_FILES ${BASE_SRC_FILES} ${X86_SRC_FILES} ${SSE41_SRC_FILES} ${SSE42_SRC_FILES} ${AVX_SRC_FILES} ${AVX2_SRC_FILES} ${MD5_SRC_FILES} ) # get all include files set( INC_FILES ${BASE_INC_FILES} ${X86_INC_FILES} ${MD5_INC_FILES} ) # library add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) if( HIGH_BITDEPTH ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( EXTENSION_360_VIDEO ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() target_include_directories( ${LIB_NAME} PUBLIC . .. ./x86 ../libmd5 ) target_link_libraries( ${LIB_NAME} Threads::Threads ) # set needed compile definitions set_property( SOURCE ${SSE41_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_SSE41 ) set_property( SOURCE ${SSE42_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_SSE42 ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_AVX ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_AVX2 ) # set needed compile flags if( MSVC ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "/arch:AVX" ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "/arch:AVX2" ) elseif( UNIX OR MINGW ) set_property( SOURCE ${SSE41_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-msse4.1" ) set_property( SOURCE ${SSE42_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-msse4.2" ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-mavx" ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-mavx2" ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib ) HM-HM-18.0/source/Lib/TLibCommon/CommonDef.h000066400000000000000000000413251442026013100202770ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file CommonDef.h \brief Defines version information, constants and small in-line functions */ #ifndef __COMMONDEF__ #define __COMMONDEF__ #include #include #undef NDEBUG #include #include #if _MSC_VER > 1000 // disable "signed and unsigned mismatch" #pragma warning( disable : 4018 ) // disable Bool coercion "performance warning" #pragma warning( disable : 4800 ) #endif // _MSC_VER > 1000 #include "TypeDef.h" #ifdef _MSC_VER #if _MSC_VER <= 1500 inline Int64 abs (Int64 x) { return _abs64(x); }; #endif #endif //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Version information // ==================================================================================================================== #define NV_VERSION "18.0" ///< Current software version // ==================================================================================================================== // Platform information // ==================================================================================================================== #ifdef __GNUC__ #define NVM_COMPILEDBY "[GCC %d.%d.%d]", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ #ifdef __IA64__ #define NVM_ONARCH "[on 64-bit] " #else #define NVM_ONARCH "[on 32-bit] " #endif #endif #ifdef __INTEL_COMPILER #define NVM_COMPILEDBY "[ICC %d]", __INTEL_COMPILER #elif _MSC_VER #define NVM_COMPILEDBY "[VS %d]", _MSC_VER #endif #ifndef NVM_COMPILEDBY #define NVM_COMPILEDBY "[Unk-CXX]" #endif #ifdef _WIN32 #define NVM_ONOS "[Windows]" #elif __linux #define NVM_ONOS "[Linux]" #elif __CYGWIN__ #define NVM_ONOS "[Cygwin]" #elif __APPLE__ #define NVM_ONOS "[Mac OS X]" #else #define NVM_ONOS "[Unk-OS]" #endif #define NVM_BITS "[%d bit] ", (sizeof(Void*) == 8 ? 64 : 32) ///< used for checking 64-bit O/S #ifndef NULL #define NULL 0 #endif // ==================================================================================================================== // Common constants // ==================================================================================================================== static const UInt MAX_UINT = 0xFFFFFFFFU; ///< max. value of unsigned 32-bit integer static const Int MAX_INT = 2147483647; ///< max. value of signed 32-bit integer static const Double MAX_DOUBLE = 1.7e+308; ///< max. value of Double-type value // ==================================================================================================================== // Coding tool configuration // ==================================================================================================================== // Most of these should not be changed - they resolve the meaning of otherwise magic numbers. static const Int MAX_GOP = 64; ///< max. value of hierarchical GOP size static const Int MAX_NUM_REF_PICS = 16; ///< max. number of pictures used for reference static const Int MAX_NUM_REF = 16; ///< max. number of entries in picture reference list static const Int MAX_QP = 51; static const Int NOT_VALID = -1; static const Int AMVP_MAX_NUM_CANDS = 2; ///< AMVP: advanced motion vector prediction - max number of final candidates static const Int AMVP_DECIMATION_FACTOR = 4; static const Int MRG_MAX_NUM_CANDS = 5; ///< MERGE static const Int MAX_TLAYER = 7; ///< Explicit temporal layer QP offset - max number of temporal layer static const Int ADAPT_SR_SCALE = 1; ///< division factor for adaptive search range static const Int MAX_NUM_PICS_IN_SOP = 1024; static const Int MAX_NESTING_NUM_OPS = 1024; static const Int MAX_NESTING_NUM_LAYER = 64; static const Int MAX_VPS_NUM_HRD_PARAMETERS = 1; static const Int MAX_VPS_OP_SETS_PLUS1 = 1024; static const Int MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 = 1; static const Int MAXIMUM_INTRA_FILTERED_WIDTH = 16; static const Int MAXIMUM_INTRA_FILTERED_HEIGHT = 16; static const Int MAX_CPB_CNT = 32; ///< Upper bound of (cpb_cnt_minus1 + 1) static const Int MAX_NUM_LAYER_IDS = 64; static const Int COEF_REMAIN_BIN_REDUCTION = 3; ///< indicates the level at which the VLC transitions from Golomb-Rice to TU+EG(k) static const Int CU_DQP_TU_CMAX = 5; ///< max number bins for truncated unary static const Int CU_DQP_EG_k = 0; ///< expgolomb order static const Int SBH_THRESHOLD = 4; ///< value of the fixed SBH controlling threshold static const Int C1FLAG_NUMBER = 8; // maximum number of largerThan1 flag coded in one chunk: 16 in HM5 static const Int C2FLAG_NUMBER = 1; // maximum number of largerThan2 flag coded in one chunk: 16 in HM5 static const Int MAX_NUM_VPS = 16; static const Int MAX_NUM_SPS = 16; static const Int MAX_NUM_PPS = 64; static const Int MLS_GRP_NUM = 64; ///< Max number of coefficient groups, max(16, 64) static const Int MLS_CG_LOG2_WIDTH = 2; static const Int MLS_CG_LOG2_HEIGHT = 2; static const Int MLS_CG_SIZE = 4; ///< Coefficient group size of 4x4; = MLS_CG_LOG2_WIDTH + MLS_CG_LOG2_HEIGHT #if ADAPTIVE_QP_SELECTION static const Int ARL_C_PRECISION = 7; ///< G382: 7-bit arithmetic precision static const Int LEVEL_RANGE = 30; ///< G382: max coefficient level in statistics collection #endif static const Int RVM_VCEGAM10_M = 4; static const Int FAST_UDI_MAX_RDMODE_NUM = 35; ///< maximum number of RD comparison in fast-UDI estimation loop static const Int NUM_INTRA_MODE = 36; static const Int PLANAR_IDX = 0; static const Int VER_IDX = 26; ///< index for intra VERTICAL mode static const Int HOR_IDX = 10; ///< index for intra HORIZONTAL mode static const Int DC_IDX = 1; ///< index for intra DC mode static const Int NUM_CHROMA_MODE = 5; ///< total number of chroma modes static const Int DM_CHROMA_IDX = 36; ///< chroma mode index for derived from luma intra mode static const Int MDCS_ANGLE_LIMIT = 4; ///< 0 = Horizontal/vertical only, 1 = Horizontal/vertical +/- 1, 2 = Horizontal/vertical +/- 2 etc... static const Int MDCS_MAXIMUM_WIDTH = 8; ///< (measured in pixels) TUs with width greater than this can only use diagonal scan static const Int MDCS_MAXIMUM_HEIGHT = 8; ///< (measured in pixels) TUs with height greater than this can only use diagonal scan static const Int LOG2_MAX_NUM_COLUMNS_MINUS1 = 7; static const Int LOG2_MAX_NUM_ROWS_MINUS1 = 7; static const Int CABAC_INIT_PRESENT_FLAG = 1; static const Int LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 4; static const Int CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 8; static const Int MAX_NUM_LONG_TERM_REF_PICS = 33; static const Int NUM_LONG_TERM_REF_PIC_SPS = 0; static const Int MAX_QP_OFFSET_LIST_SIZE = 6; ///< Maximum size of QP offset list is 6 entries // Cost mode support static const Int LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP = 0; ///< QP to use for lossless coding. static const Int LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME =4; ///< QP' to use for mixed_lossy_lossless coding. static const Int RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS = 4; static const Int RExt__GOLOMB_RICE_INCREMENT_DIVISOR = 4; static const Int RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION = 0; ///< Additional fixed bit precision used during encoder-side weighting prediction analysis. Currently only used when high_precision_prediction_weighting_flag is set, for backwards compatibility reasons. static const Int MAX_TIMECODE_SEI_SETS = 3; ///< Maximum number of time sets static const Int MAX_CU_DEPTH = 6; ///< log2(CTUSize) static const Int MAX_CU_SIZE = 64; ///< = 1<<(MAX_CU_DEPTH) static const Int MIN_PU_SIZE = 4; static const Int MIN_TU_SIZE = 4; static const Int MAX_TU_SIZE = 32; static const Int MAX_NUM_PART_IDXS_IN_CTU_WIDTH = MAX_CU_SIZE/MIN_PU_SIZE; ///< maximum number of partition indices across the width of a CTU (or height of a CTU) static const Int SCALING_LIST_REM_NUM = 6; static const Int QUANT_SHIFT = 14; ///< Q(4) = 2^14 static const Int IQUANT_SHIFT = 6; static const Int SCALE_BITS = 15; ///< For fractional bit estimates in RDOQ static const Int SCALING_LIST_NUM = MAX_NUM_COMPONENT * NUMBER_OF_PREDICTION_MODES; ///< list number for quantization matrix static const Int SCALING_LIST_START_VALUE = 8 ; ///< start value for dpcm mode static const Int MAX_MATRIX_COEF_NUM = 64 ; ///< max coefficient number for quantization matrix static const Int MAX_MATRIX_SIZE_NUM = 8 ; ///< max size number for quantization matrix static const Int SCALING_LIST_BITS = 8 ; ///< bit depth of scaling list entries static const Int LOG2_SCALING_LIST_NEUTRAL_VALUE = 4 ; ///< log2 of the value that, when used in a scaling list, has no effect on quantisation static const Int SCALING_LIST_DC = 16 ; ///< default DC value static const Int CONTEXT_STATE_BITS = 6 ; static const Int LAST_SIGNIFICANT_GROUPS = 10 ; static const Int MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS = 8 ; static const UInt LUMA_LEVEL_TO_DQP_LUT_MAXSIZE = 1024; ///< max LUT size for QP offset based on luma #if JVET_X0048_X0103_FILM_GRAIN static const Int FG_MAX_NUM_INTENSITIES = 256; // Maximum nuber of intensity intervals supported in FGC SEI static const Int FG_MAX_NUM_MODEL_VALUES = 6; // Maximum nuber of model values supported in FGC SEI static const int FG_MAX_ALLOWED_MODEL_VALUES = 3; static const int FG_MAX_ALLOWED_COMP_MODEL_PAIRS = 10; static const int FG_MAX_STANDARD_DEVIATION = 255; // for 8-bit format; for higher bit depths, internal scaling is performed static const int FG_DATA_BASE_SIZE = 64; static const int FG_BLK_8 = 8; static const int FG_BLK_16 = 16; static const int FG_BLK_32 = 32; static const int FG_BIT_DEPTH_8 = 8; #endif // ==================================================================================================================== // Macro functions // ==================================================================================================================== template inline T Clip3 (const T minVal, const T maxVal, const T a) { return std::min (std::max (minVal, a) , maxVal); } ///< general min/max clip template inline T ClipBD(const T x, const Int bitDepth) { return Clip3(T(0), T((1 << bitDepth)-1), x); } template inline Void Check3( T minVal, T maxVal, T a) { if ((a > maxVal) || (a < minVal)) { std::cerr << "ERROR: Range check " << minVal << " >= " << a << " <= " << maxVal << " failed" << std::endl; assert(false); exit(1); } } ///< general min/max clip #define DATA_ALIGN 1 ///< use 32-bit aligned malloc/free #if DATA_ALIGN && _WIN32 && ( _MSC_VER > 1300 ) #define xMalloc( type, len ) _aligned_malloc( sizeof(type)*(len), 32 ) #define xFree( ptr ) _aligned_free ( ptr ) #else #define xMalloc( type, len ) malloc ( sizeof(type)*(len) ) #define xFree( ptr ) free ( ptr ) #endif #define FATAL_ERROR_0(MESSAGE, EXITCODE) \ { \ printf(MESSAGE); \ exit(EXITCODE); \ } template inline ValueType leftShift (const ValueType value, const Int shift) { return (shift >= 0) ? ( value << shift) : ( value >> -shift); } template inline ValueType rightShift (const ValueType value, const Int shift) { return (shift >= 0) ? ( value >> shift) : ( value << -shift); } template inline ValueType leftShift_round (const ValueType value, const Int shift) { return (shift >= 0) ? ( value << shift) : ((value + (ValueType(1) << (-shift - 1))) >> -shift); } template inline ValueType rightShift_round(const ValueType value, const Int shift) { return (shift >= 0) ? ((value + (ValueType(1) << (shift - 1))) >> shift) : ( value << -shift); } #if O0043_BEST_EFFORT_DECODING // when shift = 0, returns value // when shift = 1, (value + 0 + value[1]) >> 1 // when shift = 2, (value + 1 + value[2]) >> 2 // when shift = 3, (value + 3 + value[3]) >> 3 template inline ValueType rightShiftEvenRounding(const ValueType value, const UInt shift) { return (shift == 0) ? value : ((value + (1<<(shift-1))-1 + ((value>>shift)&1)) >> shift) ; } #endif //! \} #endif // end of #ifndef __COMMONDEF__ HM-HM-18.0/source/Lib/TLibCommon/ContextModel.cpp000066400000000000000000000153441442026013100213720ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ContextModel.cpp \brief context model class */ #include #include "ContextModel.h" using namespace std; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** - initialize context model with respect to QP and initialization value . \param qp input QP value \param initValue 8 bit initialization value */ Void ContextModel::init( Int qp, Int initValue ) { qp = Clip3(0, 51, qp); Int slope = (initValue>>4)*5 - 45; Int offset = ((initValue&15)<<3)-16; Int initState = min( max( 1, ( ( ( slope * qp ) >> 4 ) + offset ) ), 126 ); UInt mpState = (initState >= 64 ); m_ucState = ( (mpState? (initState - 64):(63 - initState)) <<1) + mpState; } const UChar ContextModel::m_aucNextStateMPS[ ContextModel::m_totalStates ] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 124, 125, 126, 127 }; const UChar ContextModel::m_aucNextStateLPS[ ContextModel::m_totalStates ] = { 1, 0, 0, 1, 2, 3, 4, 5, 4, 5, 8, 9, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 18, 19, 22, 23, 22, 23, 24, 25, 26, 27, 26, 27, 30, 31, 30, 31, 32, 33, 32, 33, 36, 37, 36, 37, 38, 39, 38, 39, 42, 43, 42, 43, 44, 45, 44, 45, 46, 47, 48, 49, 48, 49, 50, 51, 52, 53, 52, 53, 54, 55, 54, 55, 56, 57, 58, 59, 58, 59, 60, 61, 60, 61, 60, 61, 62, 63, 64, 65, 64, 65, 66, 67, 66, 67, 66, 67, 68, 69, 68, 69, 70, 71, 70, 71, 70, 71, 72, 73, 72, 73, 72, 73, 74, 75, 74, 75, 74, 75, 76, 77, 76, 77, 126, 127 }; #if FAST_BIT_EST UChar ContextModel::m_nextState[ ContextModel::m_totalStates ][2 /*MPS = [0|1]*/]; Void ContextModel::buildNextStateTable() { for (Int i = 0; i < ContextModel::m_totalStates; i++) { for (Int j = 0; j < 2; j++) { m_nextState[i][j] = ((i&1) == j) ? m_aucNextStateMPS[i] : m_aucNextStateLPS[i]; } } } #endif const Int ContextModel::m_entropyBits[ ContextModel::m_totalStates ] = { #if FAST_BIT_EST // Corrected table, most notably for last state 0x07b23, 0x085f9, 0x074a0, 0x08cbc, 0x06ee4, 0x09354, 0x067f4, 0x09c1b, 0x060b0, 0x0a62a, 0x05a9c, 0x0af5b, 0x0548d, 0x0b955, 0x04f56, 0x0c2a9, 0x04a87, 0x0cbf7, 0x045d6, 0x0d5c3, 0x04144, 0x0e01b, 0x03d88, 0x0e937, 0x039e0, 0x0f2cd, 0x03663, 0x0fc9e, 0x03347, 0x10600, 0x03050, 0x10f95, 0x02d4d, 0x11a02, 0x02ad3, 0x12333, 0x0286e, 0x12cad, 0x02604, 0x136df, 0x02425, 0x13f48, 0x021f4, 0x149c4, 0x0203e, 0x1527b, 0x01e4d, 0x15d00, 0x01c99, 0x166de, 0x01b18, 0x17017, 0x019a5, 0x17988, 0x01841, 0x18327, 0x016df, 0x18d50, 0x015d9, 0x19547, 0x0147c, 0x1a083, 0x0138e, 0x1a8a3, 0x01251, 0x1b418, 0x01166, 0x1bd27, 0x01068, 0x1c77b, 0x00f7f, 0x1d18e, 0x00eda, 0x1d91a, 0x00e19, 0x1e254, 0x00d4f, 0x1ec9a, 0x00c90, 0x1f6e0, 0x00c01, 0x1fef8, 0x00b5f, 0x208b1, 0x00ab6, 0x21362, 0x00a15, 0x21e46, 0x00988, 0x2285d, 0x00934, 0x22ea8, 0x008a8, 0x239b2, 0x0081d, 0x24577, 0x007c9, 0x24ce6, 0x00763, 0x25663, 0x00710, 0x25e8f, 0x006a0, 0x26a26, 0x00672, 0x26f23, 0x005e8, 0x27ef8, 0x005ba, 0x284b5, 0x0055e, 0x29057, 0x0050c, 0x29bab, 0x004c1, 0x2a674, 0x004a7, 0x2aa5e, 0x0046f, 0x2b32f, 0x0041f, 0x2c0ad, 0x003e7, 0x2ca8d, 0x003ba, 0x2d323, 0x0010c, 0x3bfbb #else 0x08000, 0x08000, 0x076da, 0x089a0, 0x06e92, 0x09340, 0x0670a, 0x09cdf, 0x06029, 0x0a67f, 0x059dd, 0x0b01f, 0x05413, 0x0b9bf, 0x04ebf, 0x0c35f, 0x049d3, 0x0ccff, 0x04546, 0x0d69e, 0x0410d, 0x0e03e, 0x03d22, 0x0e9de, 0x0397d, 0x0f37e, 0x03619, 0x0fd1e, 0x032ee, 0x106be, 0x02ffa, 0x1105d, 0x02d37, 0x119fd, 0x02aa2, 0x1239d, 0x02836, 0x12d3d, 0x025f2, 0x136dd, 0x023d1, 0x1407c, 0x021d2, 0x14a1c, 0x01ff2, 0x153bc, 0x01e2f, 0x15d5c, 0x01c87, 0x166fc, 0x01af7, 0x1709b, 0x0197f, 0x17a3b, 0x0181d, 0x183db, 0x016d0, 0x18d7b, 0x01595, 0x1971b, 0x0146c, 0x1a0bb, 0x01354, 0x1aa5a, 0x0124c, 0x1b3fa, 0x01153, 0x1bd9a, 0x01067, 0x1c73a, 0x00f89, 0x1d0da, 0x00eb7, 0x1da79, 0x00df0, 0x1e419, 0x00d34, 0x1edb9, 0x00c82, 0x1f759, 0x00bda, 0x200f9, 0x00b3c, 0x20a99, 0x00aa5, 0x21438, 0x00a17, 0x21dd8, 0x00990, 0x22778, 0x00911, 0x23118, 0x00898, 0x23ab8, 0x00826, 0x24458, 0x007ba, 0x24df7, 0x00753, 0x25797, 0x006f2, 0x26137, 0x00696, 0x26ad7, 0x0063f, 0x27477, 0x005ed, 0x27e17, 0x0059f, 0x287b6, 0x00554, 0x29156, 0x0050e, 0x29af6, 0x004cc, 0x2a497, 0x0048d, 0x2ae35, 0x00451, 0x2b7d6, 0x00418, 0x2c176, 0x003e2, 0x2cb15, 0x003af, 0x2d4b5, 0x0037f, 0x2de55 #endif }; //! \} HM-HM-18.0/source/Lib/TLibCommon/ContextModel.h000066400000000000000000000077221442026013100210400ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ContextModel.h \brief context model class (header) */ #ifndef __CONTEXTMODEL__ #define __CONTEXTMODEL__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "CommonDef.h" #include "TComRom.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// context model class class ContextModel { public: ContextModel () { m_ucState = 0; m_binsCoded = 0; } ~ContextModel () {} UChar getState () { return ( m_ucState >> 1 ); } ///< get current state UChar getMps () { return ( m_ucState & 1 ); } ///< get curret MPS Void setStateAndMps( UChar ucState, UChar ucMPS) { m_ucState = (ucState << 1) + ucMPS; } ///< set state and MPS Void init ( Int qp, Int initValue ); ///< initialize state with initial probability Void updateLPS () { m_ucState = m_aucNextStateLPS[ m_ucState ]; } Void updateMPS () { m_ucState = m_aucNextStateMPS[ m_ucState ]; } Int getEntropyBits(Short val) { return m_entropyBits[m_ucState ^ val]; } #if FAST_BIT_EST Void update( Int binVal ) { m_ucState = m_nextState[m_ucState][binVal]; } static Void buildNextStateTable(); static Int getEntropyBitsTrm( Int val ) { return m_entropyBits[126 ^ val]; } #endif Void setBinsCoded(UInt val) { m_binsCoded = val; } UInt getBinsCoded() { return m_binsCoded; } private: UChar m_ucState; ///< internal state variable static const UInt m_totalStates = (1 << CONTEXT_STATE_BITS) * 2; //*2 for MPS = [0|1] static const UChar m_aucNextStateMPS[m_totalStates]; static const UChar m_aucNextStateLPS[m_totalStates]; static const Int m_entropyBits [m_totalStates]; #if FAST_BIT_EST static UChar m_nextState[m_totalStates][2 /*MPS = [0|1]*/]; #endif UInt m_binsCoded; }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/ContextModel3DBuffer.cpp000066400000000000000000000121571442026013100227120ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ContextModel3DBuffer.cpp \brief context model 3D buffer class */ #include "ContextModel3DBuffer.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== ContextModel3DBuffer::ContextModel3DBuffer( UInt uiSizeZ, UInt uiSizeY, UInt uiSizeX, ContextModel *basePtr, Int &count ) : m_sizeX ( uiSizeX ) , m_sizeXY ( uiSizeX * uiSizeY ) , m_sizeXYZ( uiSizeX * uiSizeY * uiSizeZ ) { // allocate 3D buffer m_contextModel = basePtr; count += m_sizeXYZ; } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** * Initialize 3D buffer with respect to slice type, QP and given initial probability table * * \param sliceType slice type * \param qp input QP value * \param ctxModel given probability table */ Void ContextModel3DBuffer::initBuffer( SliceType sliceType, Int qp, UChar* ctxModel ) { ctxModel += sliceType * m_sizeXYZ; for ( Int n = 0; n < m_sizeXYZ; n++ ) { m_contextModel[ n ].init( qp, ctxModel[ n ] ); m_contextModel[ n ].setBinsCoded( 0 ); } } /** * Calculate the cost of choosing a probability table based on the current probability of CABAC at encoder * * \param sliceType slice type * \param qp input QP value * \param ctxModel given probability table */ UInt ContextModel3DBuffer::calcCost( SliceType sliceType, Int qp, UChar* ctxModel ) { UInt cost = 0; ctxModel += sliceType * m_sizeXYZ; for ( Int n = 0; n < m_sizeXYZ; n++ ) { ContextModel tmpContextModel; tmpContextModel.init( qp, ctxModel[ n ] ); // Map the 64 CABAC states to their corresponding probability values static const Double aStateToProbLPS[] = {0.50000000, 0.47460857, 0.45050660, 0.42762859, 0.40591239, 0.38529900, 0.36573242, 0.34715948, 0.32952974, 0.31279528, 0.29691064, 0.28183267, 0.26752040, 0.25393496, 0.24103941, 0.22879875, 0.21717969, 0.20615069, 0.19568177, 0.18574449, 0.17631186, 0.16735824, 0.15885931, 0.15079198, 0.14313433, 0.13586556, 0.12896592, 0.12241667, 0.11620000, 0.11029903, 0.10469773, 0.09938088, 0.09433404, 0.08954349, 0.08499621, 0.08067986, 0.07658271, 0.07269362, 0.06900203, 0.06549791, 0.06217174, 0.05901448, 0.05601756, 0.05317283, 0.05047256, 0.04790942, 0.04547644, 0.04316702, 0.04097487, 0.03889405, 0.03691890, 0.03504406, 0.03326442, 0.03157516, 0.02997168, 0.02844963, 0.02700488, 0.02563349, 0.02433175, 0.02309612, 0.02192323, 0.02080991, 0.01975312, 0.01875000}; Double probLPS = aStateToProbLPS[ m_contextModel[ n ].getState() ]; Double prob0, prob1; if (m_contextModel[ n ].getMps()==1) { prob0 = probLPS; prob1 = 1.0-prob0; } else { prob1 = probLPS; prob0 = 1.0-prob1; } if (m_contextModel[ n ].getBinsCoded()>0) { cost += (UInt) (prob0 * tmpContextModel.getEntropyBits( 0 ) + prob1 * tmpContextModel.getEntropyBits( 1 )); } } return cost; } //! \} HM-HM-18.0/source/Lib/TLibCommon/ContextModel3DBuffer.h000066400000000000000000000073521442026013100223600ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ContextModel3DBuffer.h \brief context model 3D buffer class (header) */ #ifndef __CONTEXTMODEL3DBUFFER__ #define __CONTEXTMODEL3DBUFFER__ #include #include #include "CommonDef.h" #include "ContextModel.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// context model 3D buffer class class ContextModel3DBuffer { protected: ContextModel* m_contextModel; ///< array of context models const UInt m_sizeX; ///< X size of 3D buffer const UInt m_sizeXY; ///< X times Y size of 3D buffer const UInt m_sizeXYZ; ///< total size of 3D buffer public: ContextModel3DBuffer ( UInt uiSizeZ, UInt uiSizeY, UInt uiSizeX, ContextModel *basePtr, Int &count ); ~ContextModel3DBuffer () {} // access functions ContextModel& get( UInt uiZ, UInt uiY, UInt uiX ) { return m_contextModel[ uiZ * m_sizeXY + uiY * m_sizeX + uiX ]; } ContextModel* get( UInt uiZ, UInt uiY ) { return &m_contextModel[ uiZ * m_sizeXY + uiY * m_sizeX ]; } ContextModel* get( UInt uiZ ) { return &m_contextModel[ uiZ * m_sizeXY ]; } // initialization & copy functions Void initBuffer( SliceType eSliceType, Int iQp, UChar* ctxModel ); ///< initialize 3D buffer by slice type & QP UInt calcCost( SliceType sliceType, Int qp, UChar* ctxModel ); ///< determine cost of choosing a probability table based on current probabilities /** copy from another buffer * \param src buffer to copy from */ Void copyFrom( const ContextModel3DBuffer* src ) { assert( m_sizeXYZ == src->m_sizeXYZ ); ::memcpy( m_contextModel, src->m_contextModel, sizeof(ContextModel) * m_sizeXYZ ); } }; //! \} #endif // _HM_CONTEXT_MODEL_3DBUFFER_H_ HM-HM-18.0/source/Lib/TLibCommon/ContextTables.h000066400000000000000000000474201442026013100212110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ContextTables.h \brief Defines constants and tables for SBAC \todo number of context models is not matched to actual use, should be fixed */ #ifndef __CONTEXTTABLES__ #define __CONTEXTTABLES__ //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constants // ==================================================================================================================== #define MAX_NUM_CTX_MOD 512 ///< maximum number of supported contexts #define NUM_SPLIT_FLAG_CTX 3 ///< number of context models for split flag #define NUM_SKIP_FLAG_CTX 3 ///< number of context models for skip flag #define NUM_MERGE_FLAG_EXT_CTX 1 ///< number of context models for merge flag of merge extended #define NUM_MERGE_IDX_EXT_CTX 1 ///< number of context models for merge index of merge extended #define NUM_PART_SIZE_CTX 4 ///< number of context models for partition size #define NUM_PRED_MODE_CTX 1 ///< number of context models for prediction mode #define NUM_INTRA_PREDICT_CTX 1 ///< number of context models for intra prediction #define NUM_CHROMA_PRED_CTX 2 ///< number of context models for intra prediction (chroma) #define NUM_INTER_DIR_CTX 5 ///< number of context models for inter prediction direction #define NUM_MV_RES_CTX 2 ///< number of context models for motion vector difference #define NUM_CHROMA_QP_ADJ_FLAG_CTX 1 ///< number of context models for chroma_qp_adjustment_flag #define NUM_CHROMA_QP_ADJ_IDC_CTX 1 ///< number of context models for chroma_qp_adjustment_idc #define NUM_REF_NO_CTX 2 ///< number of context models for reference index #define NUM_TRANS_SUBDIV_FLAG_CTX 3 ///< number of context models for transform subdivision flags #define NUM_QT_ROOT_CBF_CTX 1 ///< number of context models for QT ROOT CBF #define NUM_DELTA_QP_CTX 3 ///< number of context models for dQP #define NUM_SIG_CG_FLAG_CTX 2 ///< number of context models for MULTI_LEVEL_SIGNIFICANCE #define NUM_EXPLICIT_RDPCM_FLAG_CTX 1 ///< number of context models for the flag which specifies whether to use RDPCM on inter coded residues #define NUM_EXPLICIT_RDPCM_DIR_CTX 1 ///< number of context models for the flag which specifies which RDPCM direction is used on inter coded residues //-------------------------------------------------------------------------------------------------- // context size definitions for significance map #define NUM_SIG_FLAG_CTX_LUMA 28 ///< number of context models for luma sig flag #define NUM_SIG_FLAG_CTX_CHROMA 16 ///< number of context models for chroma sig flag // |----Luma-----| |---Chroma----| static const UInt significanceMapContextSetStart [MAX_NUM_CHANNEL_TYPE][CONTEXT_NUMBER_OF_TYPES] = { {0, 9, 21, 27}, {0, 9, 12, 15} }; static const UInt significanceMapContextSetSize [MAX_NUM_CHANNEL_TYPE][CONTEXT_NUMBER_OF_TYPES] = { {9, 12, 6, 1}, {9, 3, 3, 1} }; static const UInt nonDiagonalScan8x8ContextOffset [MAX_NUM_CHANNEL_TYPE] = { 6, 0 }; static const UInt notFirstGroupNeighbourhoodContextOffset[MAX_NUM_CHANNEL_TYPE] = { 3, 0 }; //------------------ #define NEIGHBOURHOOD_00_CONTEXT_1_THRESHOLD_4x4 3 #define NEIGHBOURHOOD_00_CONTEXT_2_THRESHOLD_4x4 1 //------------------ #define FIRST_SIG_FLAG_CTX_LUMA 0 #define FIRST_SIG_FLAG_CTX_CHROMA (FIRST_SIG_FLAG_CTX_LUMA + NUM_SIG_FLAG_CTX_LUMA) #define NUM_SIG_FLAG_CTX (NUM_SIG_FLAG_CTX_LUMA + NUM_SIG_FLAG_CTX_CHROMA) ///< number of context models for sig flag //-------------------------------------------------------------------------------------------------- // context size definitions for last significant coefficient position #define NUM_CTX_LAST_FLAG_SETS 2 #define NUM_CTX_LAST_FLAG_XY 15 ///< number of context models for last coefficient position //-------------------------------------------------------------------------------------------------- // context size definitions for greater-than-one and greater-than-two maps #define NUM_ONE_FLAG_CTX_PER_SET 4 ///< number of context models for greater than 1 flag in a set #define NUM_ABS_FLAG_CTX_PER_SET 1 ///< number of context models for greater than 2 flag in a set //------------------ #define NUM_CTX_SETS_LUMA 4 ///< number of context model sets for luminance #define NUM_CTX_SETS_CHROMA 2 ///< number of context model sets for combined chrominance #define FIRST_CTX_SET_LUMA 0 ///< index of first luminance context set //------------------ #define NUM_ONE_FLAG_CTX_LUMA (NUM_ONE_FLAG_CTX_PER_SET * NUM_CTX_SETS_LUMA) ///< number of context models for greater than 1 flag of luma #define NUM_ONE_FLAG_CTX_CHROMA (NUM_ONE_FLAG_CTX_PER_SET * NUM_CTX_SETS_CHROMA) ///< number of context models for greater than 1 flag of chroma #define NUM_ABS_FLAG_CTX_LUMA (NUM_ABS_FLAG_CTX_PER_SET * NUM_CTX_SETS_LUMA) ///< number of context models for greater than 2 flag of luma #define NUM_ABS_FLAG_CTX_CHROMA (NUM_ABS_FLAG_CTX_PER_SET * NUM_CTX_SETS_CHROMA) ///< number of context models for greater than 2 flag of chroma #define NUM_ONE_FLAG_CTX (NUM_ONE_FLAG_CTX_LUMA + NUM_ONE_FLAG_CTX_CHROMA) ///< number of context models for greater than 1 flag #define NUM_ABS_FLAG_CTX (NUM_ABS_FLAG_CTX_LUMA + NUM_ABS_FLAG_CTX_CHROMA) ///< number of context models for greater than 2 flag #define FIRST_CTX_SET_CHROMA (FIRST_CTX_SET_LUMA + NUM_CTX_SETS_LUMA) ///< index of first chrominance context set //-------------------------------------------------------------------------------------------------- // context size definitions for CBF #define NUM_QT_CBF_CTX_SETS 2 #define NUM_QT_CBF_CTX_PER_SET 5 ///< number of context models for QT CBF #define FIRST_CBF_CTX_LUMA 0 ///< index of first luminance CBF context #define FIRST_CBF_CTX_CHROMA (FIRST_CBF_CTX_LUMA + NUM_QT_CBF_CTX_PER_SET) ///< index of first chrominance CBF context //-------------------------------------------------------------------------------------------------- #define NUM_MVP_IDX_CTX 1 ///< number of context models for MVP index #define NUM_SAO_MERGE_FLAG_CTX 1 ///< number of context models for SAO merge flags #define NUM_SAO_TYPE_IDX_CTX 1 ///< number of context models for SAO type index #define NUM_TRANSFORMSKIP_FLAG_CTX 1 ///< number of context models for transform skipping #define NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX 1 #define NUM_CROSS_COMPONENT_PREDICTION_CTX 10 #define CNU 154 ///< dummy initialization value for unused context models 'Context model Not Used' // ==================================================================================================================== // Tables // ==================================================================================================================== // initial probability for cu_transquant_bypass flag static const UChar INIT_CU_TRANSQUANT_BYPASS_FLAG[NUMBER_OF_SLICE_TYPES][NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX] = { { 154 }, { 154 }, { 154 }, }; // initial probability for split flag static const UChar INIT_SPLIT_FLAG[NUMBER_OF_SLICE_TYPES][NUM_SPLIT_FLAG_CTX] = { { 107, 139, 126, }, { 107, 139, 126, }, { 139, 141, 157, }, }; static const UChar INIT_SKIP_FLAG[NUMBER_OF_SLICE_TYPES][NUM_SKIP_FLAG_CTX] = { { 197, 185, 201, }, { 197, 185, 201, }, { CNU, CNU, CNU, }, }; static const UChar INIT_MERGE_FLAG_EXT[NUMBER_OF_SLICE_TYPES][NUM_MERGE_FLAG_EXT_CTX] = { { 154, }, { 110, }, { CNU, }, }; static const UChar INIT_MERGE_IDX_EXT[NUMBER_OF_SLICE_TYPES][NUM_MERGE_IDX_EXT_CTX] = { { 137, }, { 122, }, { CNU, }, }; static const UChar INIT_PART_SIZE[NUMBER_OF_SLICE_TYPES][NUM_PART_SIZE_CTX] = { { 154, 139, 154, 154 }, { 154, 139, 154, 154 }, { 184, CNU, CNU, CNU }, }; static const UChar INIT_PRED_MODE[NUMBER_OF_SLICE_TYPES][NUM_PRED_MODE_CTX] = { { 134, }, { 149, }, { CNU, }, }; static const UChar INIT_INTRA_PRED_MODE[NUMBER_OF_SLICE_TYPES][NUM_INTRA_PREDICT_CTX] = { { 183, }, { 154, }, { 184, }, }; static const UChar INIT_CHROMA_PRED_MODE[NUMBER_OF_SLICE_TYPES][NUM_CHROMA_PRED_CTX] = { { 152, 139, }, { 152, 139, }, { 63, 139, }, }; static const UChar INIT_INTER_DIR[NUMBER_OF_SLICE_TYPES][NUM_INTER_DIR_CTX] = { { 95, 79, 63, 31, 31, }, { 95, 79, 63, 31, 31, }, { CNU, CNU, CNU, CNU, CNU, }, }; static const UChar INIT_MVD[NUMBER_OF_SLICE_TYPES][NUM_MV_RES_CTX] = { { 169, 198, }, { 140, 198, }, { CNU, CNU, }, }; static const UChar INIT_REF_PIC[NUMBER_OF_SLICE_TYPES][NUM_REF_NO_CTX] = { { 153, 153 }, { 153, 153 }, { CNU, CNU }, }; static const UChar INIT_DQP[NUMBER_OF_SLICE_TYPES][NUM_DELTA_QP_CTX] = { { 154, 154, 154, }, { 154, 154, 154, }, { 154, 154, 154, }, }; static const UChar INIT_CHROMA_QP_ADJ_FLAG[NUMBER_OF_SLICE_TYPES][NUM_CHROMA_QP_ADJ_FLAG_CTX] = { { 154, }, { 154, }, { 154, }, }; static const UChar INIT_CHROMA_QP_ADJ_IDC[NUMBER_OF_SLICE_TYPES][NUM_CHROMA_QP_ADJ_IDC_CTX] = { { 154, }, { 154, }, { 154, }, }; //-------------------------------------------------------------------------------------------------- //Initialisation for CBF // |---------Luminance---------| #define BSLICE_LUMA_CBF_CONTEXT 153, 111, CNU, CNU, CNU #define PSLICE_LUMA_CBF_CONTEXT 153, 111, CNU, CNU, CNU #define ISLICE_LUMA_CBF_CONTEXT 111, 141, CNU, CNU, CNU // |--------Chrominance--------| #define BSLICE_CHROMA_CBF_CONTEXT 149, 92, 167, 154, 154 #define PSLICE_CHROMA_CBF_CONTEXT 149, 107, 167, 154, 154 #define ISLICE_CHROMA_CBF_CONTEXT 94, 138, 182, 154, 154 static const UChar INIT_QT_CBF[NUMBER_OF_SLICE_TYPES][NUM_QT_CBF_CTX_SETS * NUM_QT_CBF_CTX_PER_SET] = { { BSLICE_LUMA_CBF_CONTEXT, BSLICE_CHROMA_CBF_CONTEXT }, { PSLICE_LUMA_CBF_CONTEXT, PSLICE_CHROMA_CBF_CONTEXT }, { ISLICE_LUMA_CBF_CONTEXT, ISLICE_CHROMA_CBF_CONTEXT }, }; //-------------------------------------------------------------------------------------------------- static const UChar INIT_QT_ROOT_CBF[NUMBER_OF_SLICE_TYPES][NUM_QT_ROOT_CBF_CTX] = { { 79, }, { 79, }, { CNU, }, }; //-------------------------------------------------------------------------------------------------- //Initialisation for last-significant-position // |------------------------------Luminance----------------------------------| #define BSLICE_LUMA_LAST_POSITION_CONTEXT 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, 79 #define PSLICE_LUMA_LAST_POSITION_CONTEXT 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, 94 #define ISLICE_LUMA_LAST_POSITION_CONTEXT 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, 79 // |------------------------------Chrominance--------------------------------| #define BSLICE_CHROMA_LAST_POSITION_CONTEXT 108, 123, 93, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU #define PSLICE_CHROMA_LAST_POSITION_CONTEXT 108, 123, 108, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU #define ISLICE_CHROMA_LAST_POSITION_CONTEXT 108, 123, 63, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU static const UChar INIT_LAST[NUMBER_OF_SLICE_TYPES][NUM_CTX_LAST_FLAG_SETS * NUM_CTX_LAST_FLAG_XY] = { { BSLICE_LUMA_LAST_POSITION_CONTEXT, BSLICE_CHROMA_LAST_POSITION_CONTEXT }, { PSLICE_LUMA_LAST_POSITION_CONTEXT, PSLICE_CHROMA_LAST_POSITION_CONTEXT }, { ISLICE_LUMA_LAST_POSITION_CONTEXT, ISLICE_CHROMA_LAST_POSITION_CONTEXT }, }; //-------------------------------------------------------------------------------------------------- static const UChar INIT_SIG_CG_FLAG[NUMBER_OF_SLICE_TYPES][2 * NUM_SIG_CG_FLAG_CTX] = { { 121, 140, 61, 154, }, { 121, 140, 61, 154, }, { 91, 171, 134, 141, }, }; //-------------------------------------------------------------------------------------------------- //Initialisation for significance map // |-DC-| |-----------------4x4------------------| |------8x8 Diagonal Scan------| |----8x8 Non-Diagonal Scan----| |-NxN First group-| |-NxN Other group-| |-Single context-| // | | | | |-First Group-| |-Other Group-| |-First Group-| |-Other Group-| | | | | | | #define BSLICE_LUMA_SIGNIFICANCE_CONTEXT 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 140 #define PSLICE_LUMA_SIGNIFICANCE_CONTEXT 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 140 #define ISLICE_LUMA_SIGNIFICANCE_CONTEXT 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 141 // |-DC-| |-----------------4x4------------------| |-8x8 Any group-| |-NxN Any group-| |-Single context-| #define BSLICE_CHROMA_SIGNIFICANCE_CONTEXT 170, 153, 138, 138, 122, 121, 122, 121, 167, 151, 183, 140, 151, 183, 140, 140 #define PSLICE_CHROMA_SIGNIFICANCE_CONTEXT 170, 153, 123, 123, 107, 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, 140 #define ISLICE_CHROMA_SIGNIFICANCE_CONTEXT 140, 139, 182, 182, 152, 136, 152, 136, 153, 136, 139, 111, 136, 139, 111, 111 //------------------------------------------------ static const UChar INIT_SIG_FLAG[NUMBER_OF_SLICE_TYPES][NUM_SIG_FLAG_CTX] = { { BSLICE_LUMA_SIGNIFICANCE_CONTEXT, BSLICE_CHROMA_SIGNIFICANCE_CONTEXT }, { PSLICE_LUMA_SIGNIFICANCE_CONTEXT, PSLICE_CHROMA_SIGNIFICANCE_CONTEXT }, { ISLICE_LUMA_SIGNIFICANCE_CONTEXT, ISLICE_CHROMA_SIGNIFICANCE_CONTEXT }, }; //-------------------------------------------------------------------------------------------------- //Initialisation for greater-than-one flags and greater-than-two flags // |------Set 0-------| |------Set 1-------| |------Set 2-------| |------Set 3-------| #define BSLICE_LUMA_ONE_CONTEXT 154, 196, 167, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 122 #define PSLICE_LUMA_ONE_CONTEXT 154, 196, 196, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 137 #define ISLICE_LUMA_ONE_CONTEXT 140, 92, 137, 138, 140, 152, 138, 139, 153, 74, 149, 92, 139, 107, 122, 152 #define BSLICE_LUMA_ABS_CONTEXT 107, 167, 91, 107 #define PSLICE_LUMA_ABS_CONTEXT 107, 167, 91, 122 #define ISLICE_LUMA_ABS_CONTEXT 138, 153, 136, 167 // |------Set 4-------| |------Set 5-------| #define BSLICE_CHROMA_ONE_CONTEXT 169, 208, 166, 167, 154, 152, 167, 182 #define PSLICE_CHROMA_ONE_CONTEXT 169, 194, 166, 167, 154, 167, 137, 182 #define ISLICE_CHROMA_ONE_CONTEXT 140, 179, 166, 182, 140, 227, 122, 197 #define BSLICE_CHROMA_ABS_CONTEXT 107, 167 #define PSLICE_CHROMA_ABS_CONTEXT 107, 167 #define ISLICE_CHROMA_ABS_CONTEXT 152, 152 //------------------------------------------------ static const UChar INIT_ONE_FLAG[NUMBER_OF_SLICE_TYPES][NUM_ONE_FLAG_CTX] = { { BSLICE_LUMA_ONE_CONTEXT, BSLICE_CHROMA_ONE_CONTEXT }, { PSLICE_LUMA_ONE_CONTEXT, PSLICE_CHROMA_ONE_CONTEXT }, { ISLICE_LUMA_ONE_CONTEXT, ISLICE_CHROMA_ONE_CONTEXT }, }; static const UChar INIT_ABS_FLAG[NUMBER_OF_SLICE_TYPES][NUM_ABS_FLAG_CTX] = { { BSLICE_LUMA_ABS_CONTEXT, BSLICE_CHROMA_ABS_CONTEXT }, { PSLICE_LUMA_ABS_CONTEXT, PSLICE_CHROMA_ABS_CONTEXT }, { ISLICE_LUMA_ABS_CONTEXT, ISLICE_CHROMA_ABS_CONTEXT }, }; //-------------------------------------------------------------------------------------------------- static const UChar INIT_MVP_IDX[NUMBER_OF_SLICE_TYPES][NUM_MVP_IDX_CTX] = { { 168, }, { 168, }, { CNU, }, }; static const UChar INIT_SAO_MERGE_FLAG[NUMBER_OF_SLICE_TYPES][NUM_SAO_MERGE_FLAG_CTX] = { { 153, }, { 153, }, { 153, }, }; static const UChar INIT_SAO_TYPE_IDX[NUMBER_OF_SLICE_TYPES][NUM_SAO_TYPE_IDX_CTX] = { { 160, }, { 185, }, { 200, }, }; static const UChar INIT_TRANS_SUBDIV_FLAG[NUMBER_OF_SLICE_TYPES][NUM_TRANS_SUBDIV_FLAG_CTX] = { { 224, 167, 122, }, { 124, 138, 94, }, { 153, 138, 138, }, }; static const UChar INIT_TRANSFORMSKIP_FLAG[NUMBER_OF_SLICE_TYPES][2*NUM_TRANSFORMSKIP_FLAG_CTX] = { { 139, 139}, { 139, 139}, { 139, 139}, }; static const UChar INIT_EXPLICIT_RDPCM_FLAG[NUMBER_OF_SLICE_TYPES][2*NUM_EXPLICIT_RDPCM_FLAG_CTX] = { {139, 139}, {139, 139}, {CNU, CNU} }; static const UChar INIT_EXPLICIT_RDPCM_DIR[NUMBER_OF_SLICE_TYPES][2*NUM_EXPLICIT_RDPCM_DIR_CTX] = { {139, 139}, {139, 139}, {CNU, CNU} }; static const UChar INIT_CROSS_COMPONENT_PREDICTION[NUMBER_OF_SLICE_TYPES][NUM_CROSS_COMPONENT_PREDICTION_CTX] = { { 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 }, { 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 }, { 154, 154, 154, 154, 154, 154, 154, 154, 154, 154 }, }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/Debug.cpp000066400000000000000000000415271442026013100200150ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file Debug.cpp \brief Defines types and objects for environment-variable-based debugging and feature control */ #include "Debug.h" #include #include #include "TComDataCU.h" #include "TComPic.h" #include "TComYuv.h" static const UInt settingNameWidth = 66; static const UInt settingHelpWidth = 84; static const UInt settingValueWidth = 3; #if DEBUG_STRING // these strings are used to reorder the debug output so that the encoder and decoder match. const TChar *debug_reorder_data_inter_token[MAX_NUM_COMPONENT+1] = {"Start of channel 0 inter debug\n", "Start of channel 1 inter debug\n", "Start of channel 2 inter debug\n", "End of inter residual debug\n"} ; const TChar *partSizeToString[NUMBER_OF_PART_SIZES]={"2Nx2N(0)", "2NxN(1)", "Nx2N(2)", "NxN(3)", "2Nx(N/2+3N/2)(4)", "2Nx(3N/2+N/2)(5)", "(N/2+3N/2)x2N(6)", "(3N/2+N/2)x2N(7)"}; #endif // --------------------------------------------------------------------------------------------------------------------- // //EnvVar definition std::list > &EnvVar::getEnvVarList() { static std::list > varInfoList; return varInfoList; } std::list &EnvVar::getEnvVarInUse() { static std::list varInUseList; return varInUseList; } static inline Void printPair(const std::pair &p) { if (p.second=="") { std::cout << "\n" << std::setw(settingNameWidth) << p.first << "\n" << std::endl; } else { std::cout << std::setw(settingNameWidth) << p.first << ": " << p.second << "\n" << std::endl; } } static inline Void printVal(const EnvVar* env) { std::cout << std::setw(settingNameWidth) << env->getName() << " = " << std::setw(settingValueWidth) << env->getInt() << " (string = " << std::setw(15) << env->getString() << ")" << std::endl; } //static inline Bool sameEnvName( const std::pair &a, // const std::pair &b ) //{ // // only check env name // return (a.first==b.first); //} Void EnvVar::printEnvVar() { // getEnvVarList().unique(sameEnvName); if (getEnvVarList().size()!=0) { std::cout << "--- Environment variables:\n" << std::endl; for_each(getEnvVarList().begin(), getEnvVarList().end(), printPair); } std::cout << std::endl; } Void EnvVar::printEnvVarInUse() { if (getEnvVarInUse().size()!=0) { std::cout << "RExt Environment variables set as follows: \n" << std::endl; for_each(getEnvVarInUse().begin(), getEnvVarInUse().end(), printVal); } std::cout << std::endl; } EnvVar::EnvVar(const std::string &sName, const std::string &sDefault, const std::string &sHelp) : m_sName(sName), m_sHelp(sHelp), m_sVal(), m_dVal(0), m_iVal(0), m_bSet(false) { if (getenv(m_sName.c_str())) { m_sVal = getenv(m_sName.c_str()); m_bSet = true; getEnvVarInUse().push_back(this); } else { m_sVal = sDefault; } m_dVal = strtod(m_sVal.c_str(), 0); m_iVal = Int(m_dVal); getEnvVarList().push_back( std::pair(m_sName, indentNewLines(lineWrap(splitOnSettings(m_sHelp), settingHelpWidth), (settingNameWidth + 4))) ); } // --------------------------------------------------------------------------------------------------------------------- // // Debug environment variables: EnvVar Debug("-- Debugging","",""); EnvVar DebugOptionList::DebugSBAC ("DEBUG_SBAC", "0", "Output debug data from SBAC entropy coder (coefficient data etc.)" ); EnvVar DebugOptionList::DebugRQT ("DEBUG_RQT", "0", "Output RQT debug data from entropy coder" ); EnvVar DebugOptionList::DebugPred ("DEBUG_PRED", "0", "Output prediction debug" ); EnvVar DebugOptionList::ForceLumaMode ("FORCE_LUMA_MODE", "0", "Force a particular intra direction for Luma (0-34)" ); EnvVar DebugOptionList::ForceChromaMode ("FORCE_CHROMA_MODE", "0", "Force a particular intra direction for chroma (0-5)" ); #if DEBUG_STRING EnvVar DebugOptionList::DebugString_Structure ("DEBUG_STRUCTURE", "0", "Produce output on chosen structure bit0=intra, bit1=inter"); EnvVar DebugOptionList::DebugString_Pred ("DEBUG_PRED", "0", "Produce output on prediction data. bit0=intra, bit1=inter"); EnvVar DebugOptionList::DebugString_Resi ("DEBUG_RESI", "0", "Produce output on residual data. bit0=intra, bit1=inter"); EnvVar DebugOptionList::DebugString_Reco ("DEBUG_RECO", "0", "Produce output on reconstructed data. bit0=intra, bit1=inter"); EnvVar DebugOptionList::DebugString_InvTran ("DEBUG_INV_QT", "0", "Produce output on inverse-quantiser and transform stages. bit0=intra, bit1=inter"); #endif // --------------------------------------------------------------------------------------------------------------------- // //macro value printing function Void printMacroSettings() { std::cout << "Non-environment-variable-controlled macros set as follows: \n" << std::endl; //------------------------------------------------ //setting macros PRINT_CONSTANT(RExt__DECODER_DEBUG_BIT_STATISTICS, settingNameWidth, settingValueWidth); PRINT_CONSTANT(RExt__HIGH_BIT_DEPTH_SUPPORT, settingNameWidth, settingValueWidth); PRINT_CONSTANT(RExt__HIGH_PRECISION_FORWARD_TRANSFORM, settingNameWidth, settingValueWidth); PRINT_CONSTANT(O0043_BEST_EFFORT_DECODING, settingNameWidth, settingValueWidth); PRINT_CONSTANT(ME_ENABLE_ROUNDING_OF_MVS, settingNameWidth, settingValueWidth); //------------------------------------------------ std::cout << std::endl; } // --------------------------------------------------------------------------------------------------------------------- // //Debugging UInt g_debugCounter = 0; #if DEBUG_ENCODER_SEARCH_BINS const UInt debugEncoderSearchBinTargetLine = 0; const UInt debugEncoderSearchBinWindow = 1000000; #endif #if DEBUG_CABAC_BINS const UInt debugCabacBinTargetLine = 0; const UInt debugCabacBinWindow = 1000000; #endif Void printSBACCoeffData( const UInt lastX, const UInt lastY, const UInt width, const UInt height, const UInt chan, const UInt absPart, const UInt scanIdx, const TCoeff *const pCoeff, const Bool finalEncode ) { if (DebugOptionList::DebugSBAC.getInt()!=0 && finalEncode) { std::cout << "Size: " << width << "x" << height << ", Last X/Y: (" << lastX << ", " << lastY << "), absPartIdx: " << absPart << ", scanIdx: " << scanIdx << ", chan: " << chan << "\n"; for (Int i=0; igetWidth(0)/4; const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for (UInt ch=0; chgetCbf(compID)[g_auiRasterToZscan[y*CUSizeInParts + x]]); } } } } UInt getDecimalWidth(const Double value) { return (value == 0) ? 1 : (UInt(floor(log10(fabs(value)))) + ((value < 0) ? 2 : 1)); //for the minus sign } UInt getZScanIndex(const UInt x, const UInt y) { UInt remainingX = x; UInt remainingY = y; UInt offset = 0; UInt result = 0; while ((remainingX != 0) || (remainingY != 0)) { result |= ((remainingX & 0x1) << offset) | ((remainingY & 0x1) << (offset + 1)); remainingX >>= 1; remainingY >>= 1; offset += 2; } return result; } // --------------------------------------------------------------------------------------------------------------------- // //String manipulation functions for aligning and wrapping printed text std::string splitOnSettings(const std::string &input) { std::string result = input; std::string::size_type searchFromPosition = 0; while (searchFromPosition < result.length()) { //find the " = " that is used to define each setting std::string::size_type equalsPosition = result.find(" = ", searchFromPosition); if (equalsPosition == std::string::npos) { break; } //then find the end of the numeric characters std::string::size_type splitPosition = result.find_last_of("1234567890", equalsPosition); //then find the last space before the first numeric character... if (splitPosition != std::string::npos) { splitPosition = result.find_last_of(' ', splitPosition); } //...and replace it with a new line if (splitPosition != std::string::npos) { result.replace(splitPosition, 1, 1, '\n'); } //start the next search from the end of the " = " string searchFromPosition = (equalsPosition + 3); } return result; } std::string lineWrap(const std::string &input, const UInt maximumLineLength) { if (maximumLineLength == 0) { return input; } std::string result = input; std::string::size_type lineStartPosition = result.find_first_not_of(' '); //don't wrap any leading spaces in the string while (lineStartPosition != std::string::npos) { //------------------------------------------------ const std::string::size_type searchFromPosition = lineStartPosition + maximumLineLength; if (searchFromPosition >= result.length()) { break; } //------------------------------------------------ //first check to see if there is another new line character before the maximum line length //we can't use find for this unfortunately because it doesn't take both a beginning and an end for its search range std::string::size_type nextLineStartPosition = std::string::npos; for (std::string::size_type currentPosition = lineStartPosition; currentPosition <= searchFromPosition; currentPosition++) { if (result[currentPosition] == '\n') { nextLineStartPosition = currentPosition + 1; break; } } //------------------------------------------------ //if there ia another new line character before the maximum line length, we need to start this loop again from that position if (nextLineStartPosition != std::string::npos) { lineStartPosition = nextLineStartPosition; } else { std::string::size_type spacePosition = std::string::npos; //search backwards for the last space character (must use signed Int because lineStartPosition can be 0) for (Int currentPosition = Int(searchFromPosition); currentPosition >= Int(lineStartPosition); currentPosition--) { if (result[currentPosition] == ' ') { spacePosition = currentPosition; break; } } //if we didn't find a space searching backwards, we must hyphenate if (spacePosition == std::string::npos) { result.insert(searchFromPosition, "-\n"); lineStartPosition = searchFromPosition + 2; //make sure the next search ignores the hyphen } else //if we found a space to split on, replace it with a new line character { result.replace(spacePosition, 1, 1, '\n'); lineStartPosition = spacePosition + 1; } } //------------------------------------------------ } return result; } std::string indentNewLines(const std::string &input, const UInt indentBy) { std::string result = input; const std::string indentString(indentBy, ' '); std::string::size_type offset = 0; while ((offset = result.find('\n', offset)) != std::string::npos) { if ((++offset) >= result.length()) { break; //increment offset so we don't find the same \n again and do no indentation at the end } result.insert(offset, indentString); } return result; } // --------------------------------------------------------------------------------------------------------------------- // Void printBlockToStream( std::ostream &ss, const TChar *pLinePrefix, TComYuv &src, const UInt numSubBlocksAcross, const UInt numSubBlocksUp, const UInt defWidth ) { const UInt numValidComp=src.getNumberValidComponents(); for (UInt ch=0; ch #include #include #include #include #include #include #if DEBUG_STRING extern const TChar *debug_reorder_data_inter_token[MAX_NUM_COMPONENT+1]; extern const TChar *partSizeToString[NUMBER_OF_PART_SIZES]; #endif // ---------------------------------------------------------------------------------------------- // //constant print-out macro #define PRINT_CONSTANT(NAME, NAME_WIDTH, VALUE_WIDTH) std::cout << std::setw(NAME_WIDTH) << #NAME << " = " << std::setw(VALUE_WIDTH) << NAME << std::endl; // ---------------------------------------------------------------------------------------------- // // ---- Environment variables for test/debug ---- // class EnvVar { private: std::string m_sName; std::string m_sHelp; std::string m_sVal; Double m_dVal; Int m_iVal; Bool m_bSet; public: static std::list< std::pair > &getEnvVarList(); static std::list &getEnvVarInUse(); static Void printEnvVar(); static Void printEnvVarInUse(); EnvVar(const std::string &sName, const std::string &sDefault, const std::string &sHelp); Double getDouble() const { return m_dVal; } Int getInt() const { return m_iVal; } const std::string &getString() const { return m_sVal; } Bool isSet() const { return m_bSet; } Bool isTrue() const { return m_iVal!=0; } const std::string &getName() const { return m_sName; } }; // ---------------------------------------------------------------------------------------------- // // ---- Control switches for debugging and feature control ---- // namespace DebugOptionList { extern EnvVar DebugSBAC; extern EnvVar DebugRQT; extern EnvVar DebugPred; extern EnvVar ForceLumaMode; extern EnvVar ForceChromaMode; #if DEBUG_STRING extern EnvVar DebugString_Structure; extern EnvVar DebugString_Pred; extern EnvVar DebugString_Resi; extern EnvVar DebugString_Reco; extern EnvVar DebugString_InvTran; #endif } // ---------------------------------------------------------------------------------------------- // Void printMacroSettings(); // ---------------------------------------------------------------------------------------------- // //Debugging extern UInt g_debugCounter; #if DEBUG_ENCODER_SEARCH_BINS extern const UInt debugEncoderSearchBinTargetLine; extern const UInt debugEncoderSearchBinWindow; #endif #if DEBUG_CABAC_BINS extern const UInt debugCabacBinTargetLine; extern const UInt debugCabacBinWindow; #endif Void printSBACCoeffData( const UInt lastX, const UInt lastY, const UInt width, const UInt height, const UInt chan, const UInt absPart, const UInt scanIdx, const TCoeff *const pCoeff, const Bool finalEncode=true ); Void printCbfArray( class TComDataCU* pcCU ); UInt getDecimalWidth(const Double value); UInt getZScanIndex(const UInt x, const UInt y); //template specialisation for SChar/UChar types to get it to render as a number template inline Void writeValueToStream (const ValueType &value, std::ostream &stream, const UInt outputWidth) { stream << std::setw(outputWidth) << value; } template <> inline Void writeValueToStream(const SChar &value, std::ostream &stream, const UInt outputWidth) { stream << std::setw(outputWidth) << Int(value); } template <> inline Void writeValueToStream(const UChar &value, std::ostream &stream, const UInt outputWidth) { stream << std::setw(outputWidth) << UInt(value); } template Void printBlock(const ValueType *const source, const UInt width, const UInt height, const UInt stride, const UInt outputValueWidth = 0, //if set to 0, the maximum output width will be calculated and used const Bool onlyPrintEdges = false, //print only the top row and left column for printing prediction reference samples const Bool printInZScan = false, //output values in Z-scan format (useful for values addressed by AbsPartIdxes) const Int shiftLeftBy = 0, //set a negative value to right-shift instead const Bool printAverage = false, //also print the average of the values in the block std::ostream & stream = std::cout) { //find the maximum output width UInt outputWidth = outputValueWidth; if (outputWidth == 0) { ValueType minimumValue = leftShift(source[0], shiftLeftBy); ValueType maximumValue = minimumValue; for (UInt y = 0; y < height; y++) { for (UInt x = 0; x < width; x++) { ValueType value = 0; if (!onlyPrintEdges || (x == 0) || (y == 0)) { value = leftShift(source[printInZScan ? getZScanIndex(x, y) : ((y * stride) + x)], shiftLeftBy); } if (value < minimumValue) { minimumValue = value; } else if (value > maximumValue) { maximumValue = value; } } } outputWidth = std::max(getDecimalWidth(Double(minimumValue)), getDecimalWidth(Double(maximumValue))) + 1; //+1 so the numbers don't run into each other } //------------------ //print out the block ValueType valueSum = 0; for (UInt y = 0; y < height; y++) { for (UInt x = 0; x < width; x++) { ValueType value = 0; if (!onlyPrintEdges || (x == 0) || (y == 0)) { value = leftShift(source[printInZScan ? getZScanIndex(x, y) : ((y * stride) + x)], shiftLeftBy); valueSum += value; } writeValueToStream(value, stream, outputWidth); } stream << "\n"; } const Int valueCount = onlyPrintEdges ? Int((width + height) - 1) : Int(width * height); if (printAverage) { stream << "Average: " << (valueSum / valueCount) << "\n"; } stream << "\n"; } template Void printBlockToStream( std::ostream &ss, const TChar *pLinePrefix, const T * blkSrc, const UInt width, const UInt height, const UInt stride, const UInt subBlockWidth=0, const UInt subBlockHeight=0, const UInt defWidth=3 ) { for (UInt y=0; y #include "CommonDef.h" class TComOutputBitstream; /** * Represents a single NALunit header and the associated RBSPayload */ struct NALUnit { NalUnitType m_nalUnitType; ///< nal_unit_type UInt m_temporalId; ///< temporal_id UInt m_nuhLayerId; ///< nuh_layer_id NALUnit(const NALUnit &src) :m_nalUnitType (src.m_nalUnitType) ,m_temporalId (src.m_temporalId) ,m_nuhLayerId (src.m_nuhLayerId) { } /** construct an NALunit structure with given header values. */ NALUnit( NalUnitType nalUnitType, Int temporalId = 0, Int nuhLayerId = 0) :m_nalUnitType (nalUnitType) ,m_temporalId (temporalId) ,m_nuhLayerId (nuhLayerId) {} /** default constructor - no initialization; must be performed by user */ NALUnit() {} virtual ~NALUnit() { } /** returns true if the NALunit is a slice NALunit */ Bool isSlice() { return m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL_R || m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL_N || m_nalUnitType == NAL_UNIT_CODED_SLICE_TSA_R || m_nalUnitType == NAL_UNIT_CODED_SLICE_TSA_N || m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA_R || m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA_N || m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP || m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA || m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R; } Bool isSei() { return m_nalUnitType == NAL_UNIT_PREFIX_SEI || m_nalUnitType == NAL_UNIT_SUFFIX_SEI; } Bool isVcl() { return ( (UInt)m_nalUnitType < 32 ); } }; struct OutputNALUnit; /** * A single NALunit, with complete payload in EBSP format. */ struct NALUnitEBSP : public NALUnit { std::ostringstream m_nalUnitData; /** * convert the OutputNALUnit nalu into EBSP format by writing out * the NALUnit header, then the rbsp_bytes including any * emulation_prevention_three_byte symbols. */ NALUnitEBSP(OutputNALUnit& nalu); }; //! \} //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/ProfileLevelTierFeatures.cpp000066400000000000000000000401371442026013100236760ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ProfileLevelTierFeatures.cpp \brief Common profile tier level functions */ #include "TLibCommon/TComSlice.h" //#include "TLibCommon/TComPic.h" //#include "TLibCommon/TComPicSym.h" #include #include "ProfileLevelTierFeatures.h" UInt LevelTierFeatures::getMaxPicWidthInLumaSamples() const { return UInt(sqrt(maxLumaPs*8.0)); } UInt LevelTierFeatures::getMaxPicHeightInLumaSamples() const { return UInt(sqrt(maxLumaPs*8.0)); } static const UInt64 MAX_CNFUINT64 = std::numeric_limits::max(); static const LevelTierFeatures mainLevelTierInfo[] = { { Level::LEVEL1 , 36864, { 350, 0 }, 16, 1, 1, 552960ULL, { 128, 0 }, { 2, 2} }, { Level::LEVEL2 , 122880, { 1500, 0 }, 16, 1, 1, 3686400ULL, { 1500, 0 }, { 2, 2} }, { Level::LEVEL2_1, 245760, { 3000, 0 }, 20, 1, 1, 7372800ULL, { 3000, 0 }, { 2, 2} }, { Level::LEVEL3 , 552960, { 6000, 0 }, 30, 2, 2, 16588800ULL, { 6000, 0 }, { 2, 2} }, { Level::LEVEL3_1, 983040, { 10000, 0 }, 40, 3, 3, 33177600ULL, { 10000, 0 }, { 2, 2} }, { Level::LEVEL4 , 2228224, { 12000, 30000 }, 75, 5, 5, 66846720ULL, { 12000, 30000 }, { 4, 4} }, { Level::LEVEL4_1, 2228224, { 20000, 50000 }, 75, 5, 5, 133693440ULL, { 20000, 50000 }, { 4, 4} }, { Level::LEVEL5 , 8912896, { 25000, 100000 }, 200, 11, 10, 267386880ULL, { 25000, 100000 }, { 6, 4} }, { Level::LEVEL5_1, 8912896, { 40000, 160000 }, 200, 11, 10, 534773760ULL, { 40000, 160000 }, { 8, 4} }, { Level::LEVEL5_2, 8912896, { 60000, 240000 }, 200, 11, 10, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, { Level::LEVEL6 , 35651584, { 60000, 240000 }, 600, 22, 20, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, { Level::LEVEL6_1, 35651584, { 120000, 480000 }, 600, 22, 20, 2139095040ULL, { 120000, 480000 }, { 8, 4} }, { Level::LEVEL6_2, 35651584, { 240000, 800000 }, 600, 22, 20, 4278190080ULL, { 240000, 800000 }, { 6, 4} }, #if JVET_X0079_MODIFIED_BITRATES { Level::LEVEL6_3, 80216064, { 240000, 1600000 }, 600, 22, 20, 4812963840ULL, { 320000, 1600000 }, { 6, 4} }, #endif { Level::LEVEL8_5, MAX_UINT, { MAX_UINT, MAX_UINT }, MAX_UINT, MAX_UINT, MAX_UINT, MAX_CNFUINT64, {MAX_UINT, MAX_UINT }, { 0, 0} }, { Level::NONE } }; static const ProfileFeatures validProfiles[] = { // profile, pNameString, maxBitDepth, maxChrFmt, intra, 1pic, lowerBR, RExtTools, ExtPrec , ChrmQPOf, align, HBRFactor, , wve+t, tiles,, lvl8.5, cpbvcl, cpbnal, fcf*1000, mincr*10 { Profile::MAIN, "Main", 8, CHROMA_420, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAIN10, "Main10", 10, CHROMA_420, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1 , false, 256, 64, false, 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAIN10, "Main10 Still Picture", 10, CHROMA_420, false, true, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1 , false, 256, 64, true , 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAINSTILLPICTURE, "Main Still Picture", 8, CHROMA_420, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1 , false, 256, 64, true , 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome", 8, CHROMA_400, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 667, 733, 1000, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome 12", 12, CHROMA_400, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome 16", 16, CHROMA_400, false, false, ProfileFeatures::ENABLED , ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1333, 1467, 2000, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 12", 12, CHROMA_420, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1500, 1650, 2250, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 10", 10, CHROMA_422, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1667, 1833, 2500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 12", 12, CHROMA_422, false, false, ProfileFeatures::ENABLED , ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4", 8, CHROMA_444, false, false, ProfileFeatures::ENABLED , ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 10", 10, CHROMA_444, false, false, ProfileFeatures::ENABLED , ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2500, 2750, 3750, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 12", 12, CHROMA_444, false, false, ProfileFeatures::ENABLED , ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 3000, 3300, 4500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main Intra", 8, CHROMA_420, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 10 Intra", 10, CHROMA_420, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 12 Intra", 12, CHROMA_420, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1500, 1650, 2250, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 10 Intra", 10, CHROMA_422, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1667, 1833, 2500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 12 Intra", 12, CHROMA_422, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 Intra", 8, CHROMA_444, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 10 Intra", 10, CHROMA_444, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2500, 2750, 3750, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 12 Intra", 12, CHROMA_444, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 3000, 3300, 4500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 16 Intra", 16, CHROMA_444, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, false, 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 Still Picture", 8, CHROMA_444, true , true , ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, true , 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 16 Still Picture", 16, CHROMA_444, true , true , ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::DISABLED, HBR_1_OR_2 , false, 256, 64, true , 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::HIGHTHROUGHPUTREXT, "High Throughput 4:4:4 16 Intra", 16, CHROMA_444, true , false, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::OPTIONAL, ProfileFeatures::ENABLED , HBR_12_OR_24 , true , 256, 64, false, 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::NONE, 0 } }; Void ProfileLevelTierFeatures::activate(const TComSPS &sps) { const ProfileTierLevel ptl=*(sps.getPTL()->getGeneralPTL()); activate(ptl.getProfileIdc(), ptl.getBitDepthConstraint(), ptl.getChromaFormatConstraint(), ptl.getIntraConstraintFlag(), ptl.getOnePictureOnlyConstraintFlag(), ptl.getLevelIdc(), ptl.getTierFlag(), sps.getMaxCUWidth(), sps.getBitDepth(CHANNEL_TYPE_LUMA), sps.getBitDepth(CHANNEL_TYPE_CHROMA), sps.getChromaFormatIdc()); } Void ProfileLevelTierFeatures::activate(const Profile::Name profileIdc, const UInt bitDepthConstraint, const ChromaFormat chromaFormatConstraint, const Bool intraConstraintFlag, const Bool onePictureOnlyConstraintFlag, const Level::Name level, const Level::Tier tier, const UInt ctbSizeY, const UInt bitDepthY, const UInt bitDepthC, const ChromaFormat chFormat) { m_tier = tier; for(Int i=0; validProfiles[i].profile != Profile::NONE; i++) { if (profileIdc == validProfiles[i].profile && bitDepthConstraint == validProfiles[i].maxBitDepth && chromaFormatConstraint == validProfiles[i].maxChromaFormat && intraConstraintFlag == validProfiles[i].generalIntraConstraintFlag && onePictureOnlyConstraintFlag == validProfiles[i].generalOnePictureOnlyConstraintFlag ) { m_pProfile = &(validProfiles[i]); break; } } if (m_pProfile != 0) { // Now identify the level: const LevelTierFeatures *pLTF = m_pProfile->pLevelTiersListInfo; const Level::Name spsLevelName = level; if (spsLevelName!=Level::LEVEL8_5 || m_pProfile->bCanUseLevel8p5) { for(Int i=0; pLTF[i].level!=Level::NONE; i++) { if (pLTF[i].level == spsLevelName) { m_pLevelTier = &(pLTF[i]); } } } } { const UInt ctbWidthC = ctbSizeY >> getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, chFormat); const UInt ctbHeightC = ctbSizeY >> getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, chFormat); const UInt rawCtuBits = ctbSizeY*ctbSizeY*bitDepthY+2*(ctbWidthC*ctbHeightC)*bitDepthC; m_maxRawCtuBits=(rawCtuBits*5)/3; } } Int ProfileLevelTierFeatures::getMaxDPBNumFrames(const UInt PicSizeInSamplesY) // returns -1 if no limit, otherwise a limit of DPB pictures is indicated. { Int MaxDpbSize=-1; if (m_pLevelTier!=0) { UInt MaxLumaPs=m_pLevelTier->maxLumaPs; Int maxDpbPicBuf=6; // SCC profiles may set this to 7. if( PicSizeInSamplesY <= ( MaxLumaPs >> 2 ) ) { MaxDpbSize = min( 4 * maxDpbPicBuf, 16 ); } else if( PicSizeInSamplesY <= ( MaxLumaPs >> 1 ) ) { MaxDpbSize = min( 2 * maxDpbPicBuf, 16 ); } else if( PicSizeInSamplesY <= ( ( 3 * MaxLumaPs ) >> 2 ) ) { MaxDpbSize = min( ( 4 * maxDpbPicBuf ) / 3, 16 ); } else { MaxDpbSize = maxDpbPicBuf; } } return MaxDpbSize; } HM-HM-18.0/source/Lib/TLibCommon/ProfileLevelTierFeatures.h000066400000000000000000000150221442026013100233360ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file ProfileLevelTierFeatures.h \brief Common profile tier level functions (header) */ #ifndef __PROFILELEVELTIERFEATURES__ #define __PROFILELEVELTIERFEATURES__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include #include // Forward declarations class TComSPS; class ProfileTierLevel; typedef enum HBRFACTOREQN { HBR_1 = 0, HBR_1_OR_2 = 1, HBR_12_OR_24 = 2 } HBRFACTOREQN; struct LevelTierFeatures { Level::Name level; UInt maxLumaPs; UInt maxCpb[Level::NUMBER_OF_TIERS]; // in units of CpbVclFactor or CpbNalFactor bits UInt maxSliceSegmentsPerPicture; UInt maxTileRows; UInt maxTileCols; UInt64 maxLumaSr; UInt maxBr[Level::NUMBER_OF_TIERS]; // in units of BrVclFactor or BrNalFactor bits/s UInt minCrBase[Level::NUMBER_OF_TIERS]; UInt getMaxPicWidthInLumaSamples() const; UInt getMaxPicHeightInLumaSamples() const; }; struct ProfileFeatures { typedef enum TRISTATE { DISABLED=0, OPTIONAL=1, ENABLED=2 } TRISTATE; Profile::Name profile; const TChar *pNameString; UInt maxBitDepth; ChromaFormat maxChromaFormat; Bool generalIntraConstraintFlag; Bool generalOnePictureOnlyConstraintFlag; TRISTATE generalLowerBitRateConstraint; TRISTATE generalRExtToolsEnabled; TRISTATE extendedPrecisionProcessingFlag; TRISTATE chromaQpOffsetListEnabledFlag; TRISTATE cabacBypassAlignmentEnabledFlag; HBRFACTOREQN hbrFactorEqn; Bool bWavefrontsAndTilesCanBeUsedSimultaneously; UInt minTileColumnWidthInLumaSamples; UInt minTileRowHeightInLumaSamples; Bool bCanUseLevel8p5; UInt cpbVclFactor; UInt cpbNalFactor; // currently not used for checking UInt formatCapabilityFactorx1000; // currently not used for checking UInt minCrScaleFactorx10; // currently not used for checking const LevelTierFeatures *pLevelTiersListInfo; Bool chromaFormatValid(ChromaFormat chFmt) const { return (profile == Profile::MAINREXT || profile == Profile::HIGHTHROUGHPUTREXT) ? chFmt<=maxChromaFormat : (chFmt == maxChromaFormat ); } Bool onlyIRAPPictures() const { return generalIntraConstraintFlag; } UInt getHbrFactor(Bool bLowerBitRateConstraintFlag) const // currently not used for checking { return hbrFactorEqn==HBR_1_OR_2 ? (2-(bLowerBitRateConstraintFlag?1:0)) : (hbrFactorEqn==HBR_12_OR_24 ? 12*(2-(bLowerBitRateConstraintFlag?1:0)) : 1); } }; class ProfileLevelTierFeatures { private: const ProfileFeatures *m_pProfile; const LevelTierFeatures *m_pLevelTier; // UInt m_hbrFactor; // currently not used for checking Level::Tier m_tier; UInt m_maxRawCtuBits; public: ProfileLevelTierFeatures() : m_pProfile(0), m_pLevelTier(0), m_tier(Level::MAIN), m_maxRawCtuBits(0) { } Void activate(const Profile::Name profileIdc, const UInt bitDepthConstraint, const ChromaFormat chromaFormatConstraint, const Bool intraConstraintFlag, const Bool onePictureOnlyConstraintFlag, const Level::Name level, const Level::Tier tier, const UInt ctbSizeY, const UInt bitDepthY, const UInt bitDepthC, const ChromaFormat chFormat); Void activate(const TComSPS &sps); const ProfileFeatures *getProfileFeatures() const { return m_pProfile; } const LevelTierFeatures *getLevelTierFeatures() const { return m_pLevelTier; } Level::Tier getTier() const { return m_tier; } UInt64 getCpbSizeInBits() const { return (m_pLevelTier!=0 && m_pProfile!=0) ? UInt64(m_pProfile->cpbVclFactor) * m_pLevelTier->maxCpb[m_tier?1:0] : UInt64(0); } Double getMinCr() const { return (m_pLevelTier!=0 && m_pProfile!=0) ? (m_pProfile->minCrScaleFactorx10 * m_pLevelTier->minCrBase[m_tier?1:0])/10.0 : 0.0 ; } // currently not used for checking UInt getMaxRawCtuBits() const { return m_maxRawCtuBits; } Int getMaxDPBNumFrames(const UInt PicSizeInSamplesY); // returns -1 if no limit, otherwise a limit of DPB pictures is indicated. }; #endif HM-HM-18.0/source/Lib/TLibCommon/SEI.cpp000066400000000000000000000346301442026013100174040ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEI.cpp \brief helper functions for SEI handling */ #include "CommonDef.h" #include "SEI.h" #include const std::vector SEI::prefix_sei_messages({ SEI::BUFFERING_PERIOD, SEI::PICTURE_TIMING, SEI::PAN_SCAN_RECT, SEI::FILLER_PAYLOAD, SEI::USER_DATA_REGISTERED_ITU_T_T35, SEI::USER_DATA_UNREGISTERED, SEI::RECOVERY_POINT, SEI::SCENE_INFO, SEI::PICTURE_SNAPSHOT, SEI::PROGRESSIVE_REFINEMENT_SEGMENT_START, SEI::PROGRESSIVE_REFINEMENT_SEGMENT_END, SEI::FILM_GRAIN_CHARACTERISTICS, SEI::POST_FILTER_HINT, SEI::TONE_MAPPING_INFO, SEI::FRAME_PACKING, SEI::DISPLAY_ORIENTATION, SEI::GREEN_METADATA, SEI::SOP_DESCRIPTION, SEI::ACTIVE_PARAMETER_SETS, SEI::DECODING_UNIT_INFO, SEI::TEMPORAL_LEVEL0_INDEX, SEI::SCALABLE_NESTING, SEI::REGION_REFRESH_INFO, SEI::NO_DISPLAY, SEI::TIME_CODE, SEI::MASTERING_DISPLAY_COLOUR_VOLUME, SEI::SEGM_RECT_FRAME_PACKING, SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS, SEI::CHROMA_RESAMPLING_FILTER_HINT, SEI::KNEE_FUNCTION_INFO, SEI::COLOUR_REMAPPING_INFO, SEI::DEINTERLACE_FIELD_IDENTIFICATION, SEI::CONTENT_LIGHT_LEVEL_INFO, SEI::DEPENDENT_RAP_INDICATION, SEI::CODED_REGION_COMPLETION, SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS, SEI::AMBIENT_VIEWING_ENVIRONMENT , SEI::CONTENT_COLOUR_VOLUME , SEI::EQUIRECTANGULAR_PROJECTION , SEI::SPHERE_ROTATION , SEI::OMNI_VIEWPORT , SEI::CUBEMAP_PROJECTION , SEI::REGION_WISE_PACKING , SEI::FISHEYE_VIDEO_INFO , SEI::REGIONAL_NESTING #if SHUTTER_INTERVAL_SEI_MESSAGE , SEI::SHUTTER_INTERVAL_INFO #endif }); const std::vector SEI::suffix_sei_messages({ SEI::FILLER_PAYLOAD, SEI::USER_DATA_REGISTERED_ITU_T_T35, SEI::USER_DATA_UNREGISTERED, SEI::PROGRESSIVE_REFINEMENT_SEGMENT_END, SEI::POST_FILTER_HINT, SEI::DECODED_PICTURE_HASH, SEI::CODED_REGION_COMPLETION, }); const std::vector SEI::regional_nesting_sei_messages({ SEI::USER_DATA_REGISTERED_ITU_T_T35, SEI::USER_DATA_UNREGISTERED, SEI::FILM_GRAIN_CHARACTERISTICS, SEI::POST_FILTER_HINT, SEI::TONE_MAPPING_INFO, SEI::CHROMA_RESAMPLING_FILTER_HINT, SEI::KNEE_FUNCTION_INFO, SEI::COLOUR_REMAPPING_INFO, SEI::CONTENT_COLOUR_VOLUME, }); SEIMessages getSeisByType(SEIMessages &seiList, SEI::PayloadType seiType) { SEIMessages result; for (SEIMessages::iterator it=seiList.begin(); it!=seiList.end(); it++) { if ((*it)->payloadType() == seiType) { result.push_back(*it); } } return result; } SEIMessages extractSeisByType(SEIMessages &seiList, SEI::PayloadType seiType) { SEIMessages result; SEIMessages::iterator it=seiList.begin(); while ( it!=seiList.end() ) { if ((*it)->payloadType() == seiType) { result.push_back(*it); it = seiList.erase(it); } else { it++; } } return result; } Void deleteSEIs (SEIMessages &seiList) { for (SEIMessages::iterator it=seiList.begin(); it!=seiList.end(); it++) { delete (*it); } seiList.clear(); } void SEIBufferingPeriod::copyTo (SEIBufferingPeriod& target) { target.m_bpSeqParameterSetId = m_bpSeqParameterSetId; target.m_rapCpbParamsPresentFlag = m_rapCpbParamsPresentFlag; target.m_cpbDelayOffset = m_cpbDelayOffset; target.m_dpbDelayOffset = m_dpbDelayOffset; target.m_concatenationFlag = m_concatenationFlag; target.m_auCpbRemovalDelayDelta = m_auCpbRemovalDelayDelta; ::memcpy(target.m_initialCpbRemovalDelay, m_initialCpbRemovalDelay, sizeof(m_initialCpbRemovalDelay)); ::memcpy(target.m_initialCpbRemovalDelayOffset, m_initialCpbRemovalDelayOffset, sizeof(m_initialCpbRemovalDelayOffset)); ::memcpy(target.m_initialAltCpbRemovalDelay, m_initialAltCpbRemovalDelay, sizeof(m_initialAltCpbRemovalDelay)); ::memcpy(target.m_initialAltCpbRemovalDelayOffset, m_initialAltCpbRemovalDelayOffset, sizeof(m_initialAltCpbRemovalDelayOffset)); } void SEIPictureTiming::copyTo (SEIPictureTiming& target) { target.m_picStruct = m_picStruct; target.m_sourceScanType = m_sourceScanType; target.m_duplicateFlag = m_duplicateFlag; target.m_auCpbRemovalDelay = m_auCpbRemovalDelay; target.m_picDpbOutputDelay = m_picDpbOutputDelay; target.m_picDpbOutputDuDelay = m_picDpbOutputDuDelay; target.m_numDecodingUnitsMinus1 = m_numDecodingUnitsMinus1; target.m_duCommonCpbRemovalDelayFlag = m_duCommonCpbRemovalDelayFlag; target.m_duCommonCpbRemovalDelayMinus1 = m_duCommonCpbRemovalDelayMinus1; target.m_numNalusInDuMinus1 = m_numNalusInDuMinus1; target.m_duCpbRemovalDelayMinus1 = m_duCpbRemovalDelayMinus1; } std::ostream& operator<<(std::ostream &os, RNSEIWindow const ®ion) { os << region.getRegionId() << " " << region.getWindowLeftOffset() << region.getWindowRightOffset() << " " << region.getWindowTopOffset() << " " << region.getWindowBottomOffset() << "\n"; return os; } SEIRegionalNesting::~SEIRegionalNesting() { // Delete SEI messages for(Int i = 0; i < m_rnSeiMessages.size(); i++) { delete m_rnSeiMessages[i].m_seiMessage; } } Void SEIRegionalNesting::addRegionalSEI(RegionalSEI *regSEI) { // Check if no conflict with region IDs of regions const RNSEIWindowVec newRegions = regSEI->getRegions(); RNSEIWindowVec regionsToAdd; std::vector listOfIndices; // Loop through regions to add for(RNSEIWindowVec::const_iterator iterNew = newRegions.begin(); iterNew != newRegions.end(); iterNew++) { Bool addNewRegion = m_regions.empty() ? true : false; Bool foundRegion = false; // Loop through regions already present for(RNSEIWindowVec::const_iterator iterRef = m_regions.begin(); !foundRegion && iterRef != m_regions.end(); iterRef++) { if( (*iterNew) == (*iterRef) ) // Check if same region present { listOfIndices.push_back((UInt)(iterRef - m_regions.begin())); // Add index foundRegion = true; } else if( iterRef->checkSameID(*iterNew) ) // Check if there is a region ID class { // Two regions are different yet have same ID value; violates constraint std::cout << "Two different regions have the same ID; please check.\n"; std::cout << "Region:" << (*iterNew) << "\n"; std::cout << "Region:" << (*iterRef) << "\n"; exit(1); } } addNewRegion = !foundRegion; if(addNewRegion) { // Index is current size of the m_regions; listOfIndices.push_back((UInt)m_regions.size()); m_regions.push_back((*iterNew)); } } if(listOfIndices.empty()) { std::cout << "Unable to add regions to the regional nesting SEI.\n"; exit(1); } SEIListOfIndices seiWithListOfIndices(listOfIndices, regSEI->dissociateSEIObject()); addRegionalSEI(seiWithListOfIndices); } #if JCTVC_AD0021_SEI_MANIFEST SEIManifest::SEIManifestDescription SEIManifest::getSEIMessageDescription(const PayloadType payloadType) { std::vector necessary = { FRAME_PACKING, EQUIRECTANGULAR_PROJECTION /*,GENERALIZED_CUBEMAP_PROJECTION*/ ,SPHERE_ROTATION, REGION_WISE_PACKING }; std::vector undetermined = { USER_DATA_REGISTERED_ITU_T_T35, USER_DATA_UNREGISTERED }; for (auto pt : necessary) { if (payloadType == pt) { return NECESSARY_SEI_MESSAGE; } } for (auto pt : undetermined) { if (payloadType == pt) { return UNDETERMINED_SEI_MESSAGE; } } return UNNECESSARY_SEI_MESSAGE; } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION uint8_t SEIPrefixIndication::getNumsOfSeiPrefixIndications(const SEI* sei) { PayloadType payloadType = sei->payloadType(); //Unable to determine how many indicators are needed, it will be determined in xWriteSEIPrefixIndication() return 3 std::vector indicationN = { REGION_WISE_PACKING }; // Need two indicators to finish writing the SEI prefix indication message(return 2) std::vector indication2 = { SPHERE_ROTATION }; for (auto pt : indicationN) { if (payloadType == pt) { return 3; } } for (auto pt : indication2) { if (payloadType == pt) { return 2; } } return 1; } #endif // Static member const TChar *SEI::getSEIMessageString(SEI::PayloadType payloadType) { switch (payloadType) { case SEI::BUFFERING_PERIOD: return "Buffering period"; case SEI::PICTURE_TIMING: return "Picture timing"; case SEI::PAN_SCAN_RECT: return "Pan-scan rectangle"; case SEI::FILLER_PAYLOAD: return "Filler payload"; case SEI::USER_DATA_REGISTERED_ITU_T_T35: return "User data registered"; case SEI::USER_DATA_UNREGISTERED: return "User data unregistered"; case SEI::RECOVERY_POINT: return "Recovery point"; case SEI::SCENE_INFO: return "Scene information"; case SEI::PICTURE_SNAPSHOT: return "Picture snapshot"; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_START: return "Progressive refinement segment start"; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_END: return "Progressive refinement segment end"; case SEI::FILM_GRAIN_CHARACTERISTICS: return "Film grain characteristics"; case SEI::POST_FILTER_HINT: return "Post filter hint"; case SEI::TONE_MAPPING_INFO: return "Tone mapping information"; case SEI::KNEE_FUNCTION_INFO: return "Knee function information"; case SEI::FRAME_PACKING: return "Frame packing arrangement"; case SEI::DISPLAY_ORIENTATION: return "Display orientation"; case SEI::GREEN_METADATA: return "Green metadata information"; case SEI::SOP_DESCRIPTION: return "Structure of pictures information"; case SEI::ACTIVE_PARAMETER_SETS: return "Active parameter sets"; case SEI::DECODING_UNIT_INFO: return "Decoding unit information"; case SEI::TEMPORAL_LEVEL0_INDEX: return "Temporal sub-layer zero index"; case SEI::DECODED_PICTURE_HASH: return "Decoded picture hash"; case SEI::SCALABLE_NESTING: return "Scalable nesting"; case SEI::REGION_REFRESH_INFO: return "Region refresh information"; case SEI::NO_DISPLAY: return "No display"; case SEI::TIME_CODE: return "Time code"; case SEI::MASTERING_DISPLAY_COLOUR_VOLUME: return "Mastering display colour volume"; case SEI::SEGM_RECT_FRAME_PACKING: return "Segmented rectangular frame packing arrangement"; case SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS: return "Temporal motion constrained tile sets"; case SEI::CHROMA_RESAMPLING_FILTER_HINT: return "Chroma sampling filter hint"; case SEI::COLOUR_REMAPPING_INFO: return "Colour remapping info"; case SEI::DEINTERLACE_FIELD_IDENTIFICATION: return "Deinterlace field identification"; case SEI::CONTENT_LIGHT_LEVEL_INFO: return "Content light level info"; case SEI::DEPENDENT_RAP_INDICATION: return "Dependent RAP indication"; case SEI::CODED_REGION_COMPLETION: return "Coded region completion"; case SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS: return "Alternative transfer characteristics"; case SEI::AMBIENT_VIEWING_ENVIRONMENT: return "Ambient viewing environment"; case SEI::CONTENT_COLOUR_VOLUME: return "Content Colour Volume"; case SEI::EQUIRECTANGULAR_PROJECTION: return "Equirectangular projection"; case SEI::SPHERE_ROTATION: return "Sphere rotation"; case SEI::OMNI_VIEWPORT: return "Omni viewport"; case SEI::CUBEMAP_PROJECTION: return "Cubemap projection"; case SEI::REGION_WISE_PACKING: return "Region wise packing information"; case SEI::FISHEYE_VIDEO_INFO: return "Fisheye video information"; case SEI::REGIONAL_NESTING: return "Regional nesting"; #if MCTS_EXTRACTION case SEI::MCTS_EXTRACTION_INFO_SET: return "MCTS extraction information"; #endif #if JCTVC_AD0021_SEI_MANIFEST case SEI::SEI_MANIFEST: return "SEI manifest"; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION case SEI::SEI_PREFIX_INDICATION: return "SEI prefix indication"; #endif case SEI::ANNOTATED_REGIONS: return "Annotated Region"; #if SHUTTER_INTERVAL_SEI_MESSAGE case SEI::SHUTTER_INTERVAL_INFO: return "Shutter interval information"; #endif default: return "Unknown"; } } HM-HM-18.0/source/Lib/TLibCommon/SEI.h000066400000000000000000001075341442026013100170550ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __SEI__ #define __SEI__ #pragma once #include #include #include #include #include "CommonDef.h" #include "libmd5/MD5.h" //! \ingroup TLibCommon //! \{ class TComSPS; /** * Abstract class representing an SEI message with lightweight RTTI. */ class SEI { public: enum PayloadType { BUFFERING_PERIOD = 0, PICTURE_TIMING = 1, PAN_SCAN_RECT = 2, // TODO: add encoder command line control to create these messages FILLER_PAYLOAD = 3, // TODO: add encoder command line control to create these messages USER_DATA_REGISTERED_ITU_T_T35 = 4, // TODO: add encoder command line control to create these messages USER_DATA_UNREGISTERED = 5, // TODO: add encoder command line control to create these messages RECOVERY_POINT = 6, SCENE_INFO = 9, // TODO: add encoder command line control to create these messages PICTURE_SNAPSHOT = 15, // TODO: add encoder command line control to create these messages PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, // TODO: add encoder command line control to create these messages PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, // TODO: add encoder command line control to create these messages FILM_GRAIN_CHARACTERISTICS = 19, // TODO: add encoder command line control to create these messages POST_FILTER_HINT = 22, // TODO: add encoder command line control to create these messages TONE_MAPPING_INFO = 23, FRAME_PACKING = 45, DISPLAY_ORIENTATION = 47, GREEN_METADATA = 56, SOP_DESCRIPTION = 128, ACTIVE_PARAMETER_SETS = 129, DECODING_UNIT_INFO = 130, TEMPORAL_LEVEL0_INDEX = 131, DECODED_PICTURE_HASH = 132, SCALABLE_NESTING = 133, REGION_REFRESH_INFO = 134, NO_DISPLAY = 135, TIME_CODE = 136, MASTERING_DISPLAY_COLOUR_VOLUME = 137, SEGM_RECT_FRAME_PACKING = 138, TEMP_MOTION_CONSTRAINED_TILE_SETS = 139, CHROMA_RESAMPLING_FILTER_HINT = 140, KNEE_FUNCTION_INFO = 141, COLOUR_REMAPPING_INFO = 142, DEINTERLACE_FIELD_IDENTIFICATION = 143, // TODO: add encoder command line control to create these messages CONTENT_LIGHT_LEVEL_INFO = 144, // TODO: add encoder command line control to create these messages DEPENDENT_RAP_INDICATION = 145, // TODO: add encoder command line control to create these messages CODED_REGION_COMPLETION = 146, // TODO: add encoder command line control to create these messages ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, AMBIENT_VIEWING_ENVIRONMENT = 148, // TODO: add encoder command line control to create these messages CONTENT_COLOUR_VOLUME = 149, EQUIRECTANGULAR_PROJECTION = 150, SPHERE_ROTATION = 154, OMNI_VIEWPORT = 156, CUBEMAP_PROJECTION = 151, FISHEYE_VIDEO_INFO = 152, REGION_WISE_PACKING = 155, REGIONAL_NESTING = 157, #if MCTS_EXTRACTION MCTS_EXTRACTION_INFO_SET = 158, #endif #if JCTVC_AD0021_SEI_MANIFEST SEI_MANIFEST = 200, #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION SEI_PREFIX_INDICATION = 201, #endif ANNOTATED_REGIONS = 202, #if SHUTTER_INTERVAL_SEI_MESSAGE SHUTTER_INTERVAL_INFO = 203, #endif }; SEI() {} virtual ~SEI() {} static const TChar *getSEIMessageString(SEI::PayloadType payloadType); virtual PayloadType payloadType() const = 0; static const std::vector prefix_sei_messages; static const std::vector suffix_sei_messages; static const std::vector regional_nesting_sei_messages; }; typedef std::list SEIMessages; /// output a selection of SEI messages by payload type. Ownership stays in original message list. SEIMessages getSeisByType(SEIMessages &seiList, SEI::PayloadType seiType); /// remove a selection of SEI messages by payload type from the original list and return them in a new list. SEIMessages extractSeisByType(SEIMessages &seiList, SEI::PayloadType seiType); /// delete list of SEI messages (freeing the referenced objects) Void deleteSEIs (SEIMessages &seiList); class SEIBufferingPeriod : public SEI { public: PayloadType payloadType() const { return BUFFERING_PERIOD; } void copyTo (SEIBufferingPeriod& target); SEIBufferingPeriod() : m_bpSeqParameterSetId (0) , m_rapCpbParamsPresentFlag (false) , m_cpbDelayOffset (0) , m_dpbDelayOffset (0) { ::memset(m_initialCpbRemovalDelay, 0, sizeof(m_initialCpbRemovalDelay)); ::memset(m_initialCpbRemovalDelayOffset, 0, sizeof(m_initialCpbRemovalDelayOffset)); ::memset(m_initialAltCpbRemovalDelay, 0, sizeof(m_initialAltCpbRemovalDelay)); ::memset(m_initialAltCpbRemovalDelayOffset, 0, sizeof(m_initialAltCpbRemovalDelayOffset)); } virtual ~SEIBufferingPeriod() {} UInt m_bpSeqParameterSetId; Bool m_rapCpbParamsPresentFlag; UInt m_cpbDelayOffset; UInt m_dpbDelayOffset; UInt m_initialCpbRemovalDelay [MAX_CPB_CNT][2]; UInt m_initialCpbRemovalDelayOffset [MAX_CPB_CNT][2]; UInt m_initialAltCpbRemovalDelay [MAX_CPB_CNT][2]; UInt m_initialAltCpbRemovalDelayOffset[MAX_CPB_CNT][2]; Bool m_concatenationFlag; UInt m_auCpbRemovalDelayDelta; }; class SEIPictureTiming : public SEI { public: PayloadType payloadType() const { return PICTURE_TIMING; } void copyTo (SEIPictureTiming& target); SEIPictureTiming() : m_picStruct (0) , m_sourceScanType (0) , m_duplicateFlag (false) , m_picDpbOutputDuDelay (0) {} virtual ~SEIPictureTiming() { } UInt m_picStruct; UInt m_sourceScanType; Bool m_duplicateFlag; UInt m_auCpbRemovalDelay; UInt m_picDpbOutputDelay; UInt m_picDpbOutputDuDelay; UInt m_numDecodingUnitsMinus1; Bool m_duCommonCpbRemovalDelayFlag; UInt m_duCommonCpbRemovalDelayMinus1; std::vector m_numNalusInDuMinus1; std::vector m_duCpbRemovalDelayMinus1; }; class SEIPanScanRect : public SEI { public: PayloadType payloadType() const { return PAN_SCAN_RECT; } SEIPanScanRect() {} virtual ~SEIPanScanRect() {} struct PanScanRect { Int leftOffset; Int rightOffset; Int topOffset; Int bottomOffset; }; UInt m_panScanRectId; Bool m_panScanRectCancelFlag; std::vector m_panScanRectRegions; Bool m_panScanRectPersistenceFlag; }; class SEIFillerPayload : public SEI { public: PayloadType payloadType() const { return FILLER_PAYLOAD; } SEIFillerPayload() {} virtual ~SEIFillerPayload() {} UInt m_numFillerFFBytes; }; class SEIUserDataRegistered : public SEI { public: PayloadType payloadType() const { return USER_DATA_REGISTERED_ITU_T_T35; } SEIUserDataRegistered() {} virtual ~SEIUserDataRegistered() {} UShort m_ituCountryCode; std::vector m_userData; }; static const UInt ISO_IEC_11578_LEN=16; class SEIUserDataUnregistered : public SEI { public: PayloadType payloadType() const { return USER_DATA_UNREGISTERED; } SEIUserDataUnregistered() {} virtual ~SEIUserDataUnregistered() { } UChar m_uuid_iso_iec_11578[ISO_IEC_11578_LEN]; std::vector m_userData; }; class SEIRecoveryPoint : public SEI { public: PayloadType payloadType() const { return RECOVERY_POINT; } SEIRecoveryPoint() {} virtual ~SEIRecoveryPoint() {} Int m_recoveryPocCnt; Bool m_exactMatchingFlag; Bool m_brokenLinkFlag; }; class SEISceneInfo : public SEI { public: PayloadType payloadType() const { return SCENE_INFO; } SEISceneInfo() {} virtual ~SEISceneInfo() {} Bool m_bSceneInfoPresentFlag; Bool m_bPrevSceneIdValidFlag; UInt m_sceneId; UInt m_sceneTransitionType; UInt m_secondSceneId; }; class SEIPictureSnapshot : public SEI { public: PayloadType payloadType() const { return PICTURE_SNAPSHOT; } SEIPictureSnapshot() {} virtual ~SEIPictureSnapshot() {} UInt m_snapshotId; }; class SEIProgressiveRefinementSegmentStart : public SEI { public: PayloadType payloadType() const { return PROGRESSIVE_REFINEMENT_SEGMENT_START; } SEIProgressiveRefinementSegmentStart() {} virtual ~SEIProgressiveRefinementSegmentStart() {} UInt m_progressiveRefinementId; UInt m_picOrderCntDelta; }; class SEIProgressiveRefinementSegmentEnd: public SEI { public: PayloadType payloadType() const { return PROGRESSIVE_REFINEMENT_SEGMENT_END; } SEIProgressiveRefinementSegmentEnd() {} virtual ~SEIProgressiveRefinementSegmentEnd() {} UInt m_progressiveRefinementId; }; class SEIFilmGrainCharacteristics: public SEI { public: PayloadType payloadType() const { return FILM_GRAIN_CHARACTERISTICS; } SEIFilmGrainCharacteristics() {} virtual ~SEIFilmGrainCharacteristics() {} Bool m_filmGrainCharacteristicsCancelFlag; UChar m_filmGrainModelId; Bool m_separateColourDescriptionPresentFlag; UChar m_filmGrainBitDepthLumaMinus8; UChar m_filmGrainBitDepthChromaMinus8; Bool m_filmGrainFullRangeFlag; UChar m_filmGrainColourPrimaries; UChar m_filmGrainTransferCharacteristics; UChar m_filmGrainMatrixCoeffs; UChar m_blendingModeId; UChar m_log2ScaleFactor; struct CompModelIntensityValues { UChar intensityIntervalLowerBound; UChar intensityIntervalUpperBound; std::vector compModelValue; }; struct CompModel { Bool bPresentFlag; UChar numModelValues; // this must be the same as intensityValues[*].compModelValue.size() #if JVET_X0048_X0103_FILM_GRAIN UInt numIntensityIntervals; #endif std::vector intensityValues; }; CompModel m_compModel[MAX_NUM_COMPONENT]; Bool m_filmGrainCharacteristicsPersistenceFlag; }; class SEIPostFilterHint: public SEI { public: PayloadType payloadType() const { return POST_FILTER_HINT; } SEIPostFilterHint() {} virtual ~SEIPostFilterHint() {} UInt m_filterHintSizeY; UInt m_filterHintSizeX; UInt m_filterHintType; Bool m_bIsMonochrome; std::vector m_filterHintValues; // values stored in linear array, [ ( ( component * sizeY + y ) * SizeX ) + x ] }; class SEIToneMappingInfo : public SEI { public: PayloadType payloadType() const { return TONE_MAPPING_INFO; } SEIToneMappingInfo() {} virtual ~SEIToneMappingInfo() {} Int m_toneMapId; Bool m_toneMapCancelFlag; Bool m_toneMapPersistenceFlag; Int m_codedDataBitDepth; Int m_targetBitDepth; Int m_modelId; Int m_minValue; Int m_maxValue; Int m_sigmoidMidpoint; Int m_sigmoidWidth; std::vector m_startOfCodedInterval; Int m_numPivots; std::vector m_codedPivotValue; std::vector m_targetPivotValue; Int m_cameraIsoSpeedIdc; Int m_cameraIsoSpeedValue; Int m_exposureIndexIdc; Int m_exposureIndexValue; Bool m_exposureCompensationValueSignFlag; Int m_exposureCompensationValueNumerator; Int m_exposureCompensationValueDenomIdc; Int m_refScreenLuminanceWhite; Int m_extendedRangeWhiteLevel; Int m_nominalBlackLevelLumaCodeValue; Int m_nominalWhiteLevelLumaCodeValue; Int m_extendedWhiteLevelLumaCodeValue; }; class SEIFramePacking : public SEI { public: PayloadType payloadType() const { return FRAME_PACKING; } SEIFramePacking() {} virtual ~SEIFramePacking() {} Int m_arrangementId; Bool m_arrangementCancelFlag; Int m_arrangementType; Bool m_quincunxSamplingFlag; Int m_contentInterpretationType; Bool m_spatialFlippingFlag; Bool m_frame0FlippedFlag; Bool m_fieldViewsFlag; Bool m_currentFrameIsFrame0Flag; Bool m_frame0SelfContainedFlag; Bool m_frame1SelfContainedFlag; Int m_frame0GridPositionX; Int m_frame0GridPositionY; Int m_frame1GridPositionX; Int m_frame1GridPositionY; Int m_arrangementReservedByte; Bool m_arrangementPersistenceFlag; Bool m_upsampledAspectRatio; }; class SEIDisplayOrientation : public SEI { public: PayloadType payloadType() const { return DISPLAY_ORIENTATION; } SEIDisplayOrientation() : cancelFlag(true) , persistenceFlag(0) , extensionFlag(false) {} virtual ~SEIDisplayOrientation() {} Bool cancelFlag; Bool horFlip; Bool verFlip; UInt anticlockwiseRotation; Bool persistenceFlag; Bool extensionFlag; }; class SEIGreenMetadataInfo : public SEI { public: PayloadType payloadType() const { return GREEN_METADATA; } SEIGreenMetadataInfo() {} virtual ~SEIGreenMetadataInfo() {} UInt m_greenMetadataType; UInt m_xsdMetricType; UInt m_xsdMetricValue; }; class SEISOPDescription : public SEI { public: PayloadType payloadType() const { return SOP_DESCRIPTION; } SEISOPDescription() {} virtual ~SEISOPDescription() {} UInt m_sopSeqParameterSetId; UInt m_numPicsInSopMinus1; UInt m_sopDescVclNaluType[MAX_NUM_PICS_IN_SOP]; UInt m_sopDescTemporalId[MAX_NUM_PICS_IN_SOP]; UInt m_sopDescStRpsIdx[MAX_NUM_PICS_IN_SOP]; Int m_sopDescPocDelta[MAX_NUM_PICS_IN_SOP]; }; class SEIActiveParameterSets : public SEI { public: PayloadType payloadType() const { return ACTIVE_PARAMETER_SETS; } SEIActiveParameterSets() : activeVPSId (0) , m_selfContainedCvsFlag (false) , m_noParameterSetUpdateFlag (false) , numSpsIdsMinus1 (0) {} virtual ~SEIActiveParameterSets() {} Int activeVPSId; Bool m_selfContainedCvsFlag; Bool m_noParameterSetUpdateFlag; Int numSpsIdsMinus1; std::vector activeSeqParameterSetId; }; class SEIDecodingUnitInfo : public SEI { public: PayloadType payloadType() const { return DECODING_UNIT_INFO; } SEIDecodingUnitInfo() : m_decodingUnitIdx(0) , m_duSptCpbRemovalDelay(0) , m_dpbOutputDuDelayPresentFlag(false) , m_picSptDpbOutputDuDelay(0) {} virtual ~SEIDecodingUnitInfo() {} Int m_decodingUnitIdx; Int m_duSptCpbRemovalDelay; Bool m_dpbOutputDuDelayPresentFlag; Int m_picSptDpbOutputDuDelay; }; class SEITemporalLevel0Index : public SEI { public: PayloadType payloadType() const { return TEMPORAL_LEVEL0_INDEX; } SEITemporalLevel0Index() : tl0Idx(0) , rapIdx(0) {} virtual ~SEITemporalLevel0Index() {} UInt tl0Idx; UInt rapIdx; }; class SEIDecodedPictureHash : public SEI { public: PayloadType payloadType() const { return DECODED_PICTURE_HASH; } SEIDecodedPictureHash() {} virtual ~SEIDecodedPictureHash() {} HashType method; TComPictureHash m_pictureHash; }; class SEIScalableNesting : public SEI { public: PayloadType payloadType() const { return SCALABLE_NESTING; } SEIScalableNesting() {} virtual ~SEIScalableNesting() { deleteSEIs(m_nestedSEIs); } Bool m_bitStreamSubsetFlag; Bool m_nestingOpFlag; Bool m_defaultOpFlag; //value valid if m_nestingOpFlag != 0 UInt m_nestingNumOpsMinus1; // -"- UInt m_nestingMaxTemporalIdPlus1[MAX_TLAYER]; // -"- UInt m_nestingOpIdx[MAX_NESTING_NUM_OPS]; // -"- Bool m_allLayersFlag; //value valid if m_nestingOpFlag == 0 UInt m_nestingNoOpMaxTemporalIdPlus1; //value valid if m_nestingOpFlag == 0 and m_allLayersFlag == 0 UInt m_nestingNumLayersMinus1; //value valid if m_nestingOpFlag == 0 and m_allLayersFlag == 0 UChar m_nestingLayerId[MAX_NESTING_NUM_LAYER]; //value valid if m_nestingOpFlag == 0 and m_allLayersFlag == 0. This can e.g. be a static array of 64 UChar values SEIMessages m_nestedSEIs; }; class SEIRegionRefreshInfo : public SEI { public: PayloadType payloadType() const { return REGION_REFRESH_INFO; } SEIRegionRefreshInfo() : m_gdrForegroundFlag(0) {} virtual ~SEIRegionRefreshInfo() {} Bool m_gdrForegroundFlag; }; class SEINoDisplay : public SEI { public: PayloadType payloadType() const { return NO_DISPLAY; } SEINoDisplay() : m_noDisplay(false) {} virtual ~SEINoDisplay() {} Bool m_noDisplay; }; class SEITimeCode : public SEI { public: PayloadType payloadType() const { return TIME_CODE; } SEITimeCode() {} virtual ~SEITimeCode(){} UInt numClockTs; TComSEITimeSet timeSetArray[MAX_TIMECODE_SEI_SETS]; }; class SEIMasteringDisplayColourVolume : public SEI { public: PayloadType payloadType() const { return MASTERING_DISPLAY_COLOUR_VOLUME; } SEIMasteringDisplayColourVolume() {} virtual ~SEIMasteringDisplayColourVolume(){} TComSEIMasteringDisplay values; }; class SEISegmentedRectFramePacking : public SEI { public: PayloadType payloadType() const { return SEGM_RECT_FRAME_PACKING; } SEISegmentedRectFramePacking() {} virtual ~SEISegmentedRectFramePacking() {} Bool m_arrangementCancelFlag; Int m_contentInterpretationType; Bool m_arrangementPersistenceFlag; }; //definition according to P1005_v1; class SEITempMotionConstrainedTileSets: public SEI { class TileSetData { protected: std::vector m_top_left_tile_index; //[tileSetIdx][tileIdx]; std::vector m_bottom_right_tile_index; public: Int m_mcts_id; Bool m_display_tile_set_flag; Int m_num_tile_rects_in_set; //_minus1; Bool m_exact_sample_value_match_flag; Bool m_mcts_tier_level_idc_present_flag; Bool m_mcts_tier_flag; Int m_mcts_level_idc; Void setNumberOfTileRects(const Int number) { m_top_left_tile_index .resize(number); m_bottom_right_tile_index.resize(number); } Int getNumberOfTileRects() const { assert(m_top_left_tile_index.size() == m_bottom_right_tile_index.size()); return Int(m_top_left_tile_index.size()); } Int &topLeftTileIndex (const Int tileRectIndex) { return m_top_left_tile_index [tileRectIndex]; } Int &bottomRightTileIndex(const Int tileRectIndex) { return m_bottom_right_tile_index[tileRectIndex]; } const Int &topLeftTileIndex (const Int tileRectIndex) const { return m_top_left_tile_index [tileRectIndex]; } const Int &bottomRightTileIndex(const Int tileRectIndex) const { return m_bottom_right_tile_index[tileRectIndex]; } }; protected: std::vector m_tile_set_data; public: Bool m_mc_all_tiles_exact_sample_value_match_flag; Bool m_each_tile_one_tile_set_flag; Bool m_limited_tile_set_display_flag; Bool m_max_mcs_tier_level_idc_present_flag; Bool m_max_mcts_tier_flag; Int m_max_mcts_level_idc; PayloadType payloadType() const { return TEMP_MOTION_CONSTRAINED_TILE_SETS; } SEITempMotionConstrainedTileSets() { } virtual ~SEITempMotionConstrainedTileSets() { } Void setNumberOfTileSets(const Int number) { m_tile_set_data.resize(number); } Int getNumberOfTileSets() const { return Int(m_tile_set_data.size()); } TileSetData &tileSetData (const Int index) { return m_tile_set_data[index]; } const TileSetData &tileSetData (const Int index) const { return m_tile_set_data[index]; } }; class SEIChromaResamplingFilterHint : public SEI { public: PayloadType payloadType() const {return CHROMA_RESAMPLING_FILTER_HINT;} SEIChromaResamplingFilterHint() {} virtual ~SEIChromaResamplingFilterHint() {} Int m_verChromaFilterIdc; Int m_horChromaFilterIdc; Bool m_verFilteringFieldProcessingFlag; Int m_targetFormatIdc; Bool m_perfectReconstructionFlag; std::vector > m_verFilterCoeff; std::vector > m_horFilterCoeff; }; class SEIKneeFunctionInfo : public SEI { public: PayloadType payloadType() const { return KNEE_FUNCTION_INFO; } SEIKneeFunctionInfo() {} virtual ~SEIKneeFunctionInfo() {} Int m_kneeId; Bool m_kneeCancelFlag; Bool m_kneePersistenceFlag; Int m_kneeInputDrange; Int m_kneeInputDispLuminance; Int m_kneeOutputDrange; Int m_kneeOutputDispLuminance; Int m_kneeNumKneePointsMinus1; std::vector m_kneeInputKneePoint; std::vector m_kneeOutputKneePoint; }; class SEIContentColourVolume : public SEI { public: PayloadType payloadType() const { return CONTENT_COLOUR_VOLUME; } SEIContentColourVolume() {} virtual ~SEIContentColourVolume() {} Bool m_ccvCancelFlag; Bool m_ccvPersistenceFlag; Bool m_ccvPrimariesPresentFlag; Bool m_ccvMinLuminanceValuePresentFlag; Bool m_ccvMaxLuminanceValuePresentFlag; Bool m_ccvAvgLuminanceValuePresentFlag; Int m_ccvPrimariesX[MAX_NUM_COMPONENT]; Int m_ccvPrimariesY[MAX_NUM_COMPONENT]; UInt m_ccvMinLuminanceValue; UInt m_ccvMaxLuminanceValue; UInt m_ccvAvgLuminanceValue; }; class SEIEquirectangularProjection : public SEI { public: PayloadType payloadType() const { return EQUIRECTANGULAR_PROJECTION; } SEIEquirectangularProjection() {} virtual ~SEIEquirectangularProjection() {} Bool m_erpCancelFlag; Bool m_erpPersistenceFlag; Bool m_erpGuardBandFlag; UChar m_erpGuardBandType; UChar m_erpLeftGuardBandWidth; UChar m_erpRightGuardBandWidth; }; class SEISphereRotation : public SEI { public: PayloadType payloadType() const { return SPHERE_ROTATION; } SEISphereRotation() {} virtual ~SEISphereRotation() {} Bool m_sphereRotationCancelFlag; Bool m_sphereRotationPersistenceFlag; Int m_sphereRotationYaw; Int m_sphereRotationPitch; Int m_sphereRotationRoll; }; class SEIOmniViewport : public SEI { public: PayloadType payloadType() const { return OMNI_VIEWPORT; } SEIOmniViewport() {} virtual ~SEIOmniViewport() {} struct OmniViewport { Int azimuthCentre; Int elevationCentre; Int tiltCentre; UInt horRange; UInt verRange; }; UInt m_omniViewportId; Bool m_omniViewportCancelFlag; Bool m_omniViewportPersistenceFlag; UChar m_omniViewportCntMinus1; std::vector m_omniViewportRegions; }; class SEIAnnotatedRegions : public SEI { public: PayloadType payloadType() const { return ANNOTATED_REGIONS; } SEIAnnotatedRegions() {} virtual ~SEIAnnotatedRegions() {} Void copyFrom(const SEIAnnotatedRegions &seiAnnotatedRegions) { (*this) = seiAnnotatedRegions; } struct AnnotatedRegionObject { AnnotatedRegionObject() : objectCancelFlag(false), objectLabelValid(false), boundingBoxValid(false) { } Bool objectCancelFlag; Bool objectLabelValid; UInt objLabelIdx; // only valid if bObjectLabelValid Bool boundingBoxValid; Bool boundingBoxCancelFlag; UInt boundingBoxTop; // only valid if bBoundingBoxValid UInt boundingBoxLeft; UInt boundingBoxWidth; UInt boundingBoxHeight; Bool partialObjectFlag; // only valid if bPartialObjectFlagValid UInt objectConfidence; }; struct AnnotatedRegionLabel { AnnotatedRegionLabel() : labelValid(false) { } Bool labelValid; std::string label; // only valid if bLabelValid }; struct AnnotatedRegionHeader { AnnotatedRegionHeader() : m_cancelFlag(true), m_receivedSettingsOnce(false) { } Bool m_cancelFlag; Bool m_receivedSettingsOnce; // used for decoder conformance checking. Other confidence flags must be unchanged once this flag is set. Bool m_notOptimizedForViewingFlag; Bool m_trueMotionFlag; Bool m_occludedObjectFlag; Bool m_partialObjectFlagPresentFlag; Bool m_objectLabelPresentFlag; Bool m_objectConfidenceInfoPresentFlag; UInt m_objectConfidenceLength; // Only valid if m_objectConfidenceInfoPresentFlag Bool m_objectLabelLanguagePresentFlag; // Only valid if m_objectLabelPresentFlag std::string m_annotatedRegionsObjectLabelLang; }; typedef UInt AnnotatedRegionObjectIndex; typedef UInt AnnotatedRegionLabelIndex; AnnotatedRegionHeader m_hdr; std::vector > m_annotatedRegions; std::vector > m_annotatedLabels; }; class SEICubemapProjection : public SEI { public: PayloadType payloadType() const { return CUBEMAP_PROJECTION; } SEICubemapProjection() {} virtual ~SEICubemapProjection() {} Bool m_cmpCancelFlag; Bool m_cmpPersistenceFlag; }; class SEIRegionWisePacking : public SEI { public: PayloadType payloadType() const { return REGION_WISE_PACKING; } SEIRegionWisePacking() {} virtual ~SEIRegionWisePacking() {} Bool m_rwpCancelFlag; Bool m_rwpPersistenceFlag; Bool m_constituentPictureMatchingFlag; Int m_numPackedRegions; Int m_projPictureWidth; Int m_projPictureHeight; Int m_packedPictureWidth; Int m_packedPictureHeight; std::vector m_rwpTransformType; std::vector m_rwpGuardBandFlag; std::vector m_projRegionWidth; std::vector m_projRegionHeight; std::vector m_rwpProjRegionTop; std::vector m_projRegionLeft; std::vector m_packedRegionWidth; std::vector m_packedRegionHeight; std::vector m_packedRegionTop; std::vector m_packedRegionLeft; std::vector m_rwpLeftGuardBandWidth; std::vector m_rwpRightGuardBandWidth; std::vector m_rwpTopGuardBandHeight; std::vector m_rwpBottomGuardBandHeight; std::vector m_rwpGuardBandNotUsedForPredFlag; std::vector m_rwpGuardBandType; }; class SEIFisheyeVideoInfo : public SEI { public: PayloadType payloadType() const { return FISHEYE_VIDEO_INFO; } SEIFisheyeVideoInfo() {} virtual ~SEIFisheyeVideoInfo() {} TComSEIFisheyeVideoInfo values; }; #if SHUTTER_INTERVAL_SEI_MESSAGE class SEIShutterIntervalInfo : public SEI { public: PayloadType payloadType() const { return SHUTTER_INTERVAL_INFO; } SEIShutterIntervalInfo() {} virtual ~SEIShutterIntervalInfo() {} Bool m_siiEnabled; UInt m_siiNumUnitsInShutterInterval; UInt m_siiTimeScale; UInt m_siiMaxSubLayersMinus1; Bool m_siiFixedSIwithinCLVS; std::vector m_siiSubLayerNumUnitsInSI; }; #endif class SEIColourRemappingInfo : public SEI { public: struct CRIlut { Int codedValue; Int targetValue; bool operator < (const CRIlut& a) const { return codedValue < a.codedValue; } }; PayloadType payloadType() const { return COLOUR_REMAPPING_INFO; } SEIColourRemappingInfo() {} ~SEIColourRemappingInfo() {} Void copyFrom( const SEIColourRemappingInfo &seiCriInput) { (*this) = seiCriInput; } UInt m_colourRemapId; Bool m_colourRemapCancelFlag; Bool m_colourRemapPersistenceFlag; Bool m_colourRemapVideoSignalInfoPresentFlag; Bool m_colourRemapFullRangeFlag; Int m_colourRemapPrimaries; Int m_colourRemapTransferFunction; Int m_colourRemapMatrixCoefficients; Int m_colourRemapInputBitDepth; Int m_colourRemapBitDepth; Int m_preLutNumValMinus1[3]; std::vector m_preLut[3]; Bool m_colourRemapMatrixPresentFlag; Int m_log2MatrixDenom; Int m_colourRemapCoeffs[3][3]; Int m_postLutNumValMinus1[3]; std::vector m_postLut[3]; }; class SEIDeinterlaceFieldIdentification : public SEI { public: PayloadType payloadType() const { return DEINTERLACE_FIELD_IDENTIFICATION; } SEIDeinterlaceFieldIdentification() { } virtual ~SEIDeinterlaceFieldIdentification() {} Bool m_deinterlacedPictureSourceParityFlag; }; class SEIContentLightLevelInfo : public SEI { public: PayloadType payloadType() const { return CONTENT_LIGHT_LEVEL_INFO; } SEIContentLightLevelInfo() { } virtual ~SEIContentLightLevelInfo() { } UInt m_maxContentLightLevel; UInt m_maxPicAverageLightLevel; }; class SEIDependentRAPIndication : public SEI { public: PayloadType payloadType() const { return DEPENDENT_RAP_INDICATION; } SEIDependentRAPIndication() { } virtual ~SEIDependentRAPIndication() { } }; class SEICodedRegionCompletion : public SEI { public: PayloadType payloadType() const { return CODED_REGION_COMPLETION; } SEICodedRegionCompletion() { } virtual ~SEICodedRegionCompletion() { } UInt m_nextSegmentAddress; Bool m_independentSliceSegmentFlag; }; class SEIAlternativeTransferCharacteristics : public SEI { public: PayloadType payloadType() const { return ALTERNATIVE_TRANSFER_CHARACTERISTICS; } SEIAlternativeTransferCharacteristics() : m_preferredTransferCharacteristics(18) { } virtual ~SEIAlternativeTransferCharacteristics() {} UInt m_preferredTransferCharacteristics; }; class SEIAmbientViewingEnvironment : public SEI { public: PayloadType payloadType() const { return AMBIENT_VIEWING_ENVIRONMENT; } SEIAmbientViewingEnvironment() { } virtual ~SEIAmbientViewingEnvironment() { } UInt m_ambientIlluminance; UShort m_ambientLightX; UShort m_ambientLightY; }; #if MCTS_EXTRACTION class SEIMCTSExtractionInfoSet : public SEI { public: struct MCTSExtractionInfo { std::vector< std::vector > m_idxOfMctsInSet; Bool m_sliceReorderingEnabledFlag; std::vector m_outputSliceSegmentAddress; std::vector m_vpsRbspDataLength; std::vector m_spsRbspDataLength; std::vector m_ppsNuhTemporalIdPlus1; std::vector m_ppsRbspDataLength; std::vector< std::vector > m_vpsRbspData; std::vector< std::vector > m_spsRbspData; std::vector< std::vector > m_ppsRbspData; UInt mctsWidth; UInt mctsHeight; }; PayloadType payloadType() const { return MCTS_EXTRACTION_INFO_SET; } SEIMCTSExtractionInfoSet() { } virtual ~SEIMCTSExtractionInfoSet() { } std::vector m_MCTSExtractionInfoSets; }; #endif #endif // Class that associates an SEI with one more regions class RegionalSEI { public: RegionalSEI(): m_seiMessage(NULL) {} RegionalSEI(SEI *sei, RNSEIWindowVec ®ions) { if( checkRegionalNestedSEIPayloadType(sei->payloadType()) ) { m_seiMessage = sei; m_regions = regions; } else { m_seiMessage = sei; } } ~RegionalSEI() { if(!m_seiMessage) { delete m_seiMessage; } } SEI *dissociateSEIObject() // Dissociates SEI; receiver of this function in charge of memory deallocation. { SEI *temp = m_seiMessage; m_seiMessage = NULL; return temp; } UInt getNumRegions() const { return (UInt) m_regions.size(); } const RNSEIWindowVec& getRegions() { return m_regions; } Void addRegions(RNSEIWindowVec const ®ions) { m_regions.insert(m_regions.end(), regions.begin(), regions.end()); } static Bool checkRegionalNestedSEIPayloadType(SEI::PayloadType const payloadType) { switch(payloadType) { case SEI::USER_DATA_REGISTERED_ITU_T_T35: case SEI::USER_DATA_UNREGISTERED: case SEI::FILM_GRAIN_CHARACTERISTICS: case SEI::POST_FILTER_HINT: case SEI::TONE_MAPPING_INFO: case SEI::CHROMA_RESAMPLING_FILTER_HINT: case SEI::KNEE_FUNCTION_INFO: case SEI::COLOUR_REMAPPING_INFO: case SEI::CONTENT_COLOUR_VOLUME: return true; default: return false; } } private: SEI *m_seiMessage; RNSEIWindowVec m_regions; }; class SEIRegionalNesting : public SEI { public: SEIRegionalNesting(): m_rnId(0) {} ~SEIRegionalNesting(); struct SEIListOfIndices { std::vector m_listOfIndices; SEI *m_seiMessage; SEIListOfIndices() : m_seiMessage(NULL) {} SEIListOfIndices(std::vector listOfIndices, SEI* sei) : m_listOfIndices(listOfIndices), m_seiMessage(sei) {} }; PayloadType payloadType() const { return REGIONAL_NESTING; } UInt getNumRnSEIMessage() const { return (UInt) m_rnSeiMessages.size(); } UInt getNumRectRegions() const { return (UInt) m_regions.size(); } UInt getRNId() const { return m_rnId; } Void addRegion(RNSEIWindow *regn) { m_regions.push_back(*regn); } Void clearRegions() { m_regions.clear(); } Void addRegionalSEI(SEIListOfIndices const &seiWithListOfRegionIndices) { m_rnSeiMessages.push_back(seiWithListOfRegionIndices); } Void addRegionalSEI(RegionalSEI *regSEI); const std::vector< SEIListOfIndices >& getRnSEIMessages() const { return m_rnSeiMessages; } const std::vector &getRegions() const { return m_regions; } private: UInt m_rnId; RNSEIWindowVec m_regions; std::vector< SEIListOfIndices > m_rnSeiMessages; }; #if JCTVC_AD0021_SEI_MANIFEST class SEIManifest : public SEI { public: PayloadType payloadType() const { return SEI_MANIFEST; } SEIManifest() {} virtual ~SEIManifest() {} enum SEIManifestDescription { NO_SEI_MESSAGE = 0, NECESSARY_SEI_MESSAGE = 1, UNNECESSARY_SEI_MESSAGE = 2, UNDETERMINED_SEI_MESSAGE = 3, NUM_OF_DESCROPTION = 255, }; uint16_t m_manifestNumSeiMsgTypes; std::vector m_manifestSeiPayloadType; std::vector m_manifestSeiDescription; SEIManifestDescription getSEIMessageDescription(const PayloadType payloadType); }; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION class SEIPrefixIndication : public SEI { public: PayloadType payloadType() const { return SEI_PREFIX_INDICATION; } SEIPrefixIndication() {} virtual ~SEIPrefixIndication() {} uint16_t m_prefixSeiPayloadType; uint8_t m_numSeiPrefixIndicationsMinus1; std::vector m_numBitsInPrefixIndicationMinus1; std::vector> m_seiPrefixDataBit; const SEI* m_payload; uint8_t getNumsOfSeiPrefixIndications(const SEI* sei); }; #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/SEIFilmGrainAnalyzer.cpp000066400000000000000000001733241442026013100227070ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2021, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainAnalyzer.cpp \brief SMPTE RDD5 based film grain analysis functionality from SEI messages */ #include "SEIFilmGrainAnalyzer.h" #if JVET_X0048_X0103_FILM_GRAIN // ==================================================================================================================== // Edge detection - Canny // ==================================================================================================================== const int Canny::m_gx[3][3]{ { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }; const int Canny::m_gy[3][3]{ { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } }; const int Canny::m_gauss5x5[5][5]{ { 2, 4, 5, 4, 2 }, { 4, 9, 12, 9, 4 }, { 5, 12, 15, 12, 5 }, { 4, 9, 12, 9, 4 }, { 2, 4, 5, 4, 2 } }; Canny::Canny() { // init(); } Canny::~Canny() { // uninit(); } void Canny::gradient(TComPicYuv* buff1, TComPicYuv* buff2, unsigned int width, unsigned int height, unsigned int convWidthS, unsigned int convHeightS, unsigned int bitDepth, ComponentID compID) { /* buff1 - magnitude; buff2 - orientation (Only luma in buff2) */ // 360 degrees are split into the 8 equal parts; edge direction is quantized const double edge_threshold_22_5 = 22.5; const double edge_threshold_67_5 = 67.5; const double edge_threshold_112_5 = 112.5; const double edge_threshold_157_5 = 157.5; const int maxClpRange = (1 << bitDepth) - 1; const int padding = convWidthS / 2; // tmp buffs TComPicYuv* tmpBuf1 = new TComPicYuv; TComPicYuv* tmpBuf2 = new TComPicYuv; tmpBuf1->createWithPadding(width, height, CHROMA_400); tmpBuf2->createWithPadding(width, height, CHROMA_400); buff1->extendPicBorder(compID, padding, padding, false); // Gx for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int acc = 0; for (int x = 0; x < convWidthS; x++) { for (int y = 0; y < convHeightS; y++) { acc += (buff1->at(x - convWidthS / 2 + i, y - convHeightS / 2 + j, compID, false) * m_gx[x][y]); } } tmpBuf1->at(i, j, ComponentID(0), false) = acc; } } // Gy for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int acc = 0; for (int x = 0; x < convWidthS; x++) { for (int y = 0; y < convHeightS; y++) { acc += (buff1->at(x - convWidthS / 2 + i, y - convHeightS / 2 + j, compID, false) * m_gy[x][y]); } } tmpBuf2->at(i, j, ComponentID(0), false) = acc; } } // magnitude for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { Pel tmp = (Pel)((abs(tmpBuf1->at(i, j, ComponentID(0), false)) + abs(tmpBuf2->at(i, j, ComponentID(0), false))) / 2); buff1->at(i, j, compID, false) = (Pel) Clip3((Pel) 0, (Pel) maxClpRange, tmp); } } // edge direction - quantized edge directions for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { double theta = (atan2(tmpBuf1->at(i, j, ComponentID(0), false), tmpBuf2->at(i, j, ComponentID(0), false)) * 180) / PI; /* Convert actual edge direction to approximate value - quantize directions */ if (((-edge_threshold_22_5 < theta) && (theta <= edge_threshold_22_5)) || ((edge_threshold_157_5 < theta) || (theta <= -edge_threshold_157_5))) buff2->at(i, j, ComponentID(0), false) = 0; if (((-edge_threshold_157_5 < theta) && (theta <= -edge_threshold_112_5)) || ((edge_threshold_22_5 < theta) && (theta <= edge_threshold_67_5))) buff2->at(i, j, ComponentID(0), false) = 45; if (((-edge_threshold_112_5 < theta) && (theta <= -edge_threshold_67_5)) || ((edge_threshold_67_5 < theta) && (theta <= edge_threshold_112_5))) buff2->at(i, j, ComponentID(0), false) = 90; if (((-edge_threshold_67_5 < theta) && (theta <= -edge_threshold_22_5)) || ((edge_threshold_112_5 < theta) && (theta <= edge_threshold_157_5))) buff2->at(i, j, ComponentID(0), false) = 135; } } buff1->extendPicBorder(compID, padding, padding, false); // extend border for the next steps tmpBuf1->destroy(); tmpBuf2->destroy(); delete tmpBuf1; tmpBuf1 = nullptr; delete tmpBuf2; tmpBuf2 = nullptr; } void Canny::suppressNonMax(TComPicYuv* buff1, TComPicYuv* buff2, unsigned int width, unsigned int height, ComponentID compID) { for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int rowShift = 0, colShift = 0; switch (buff2->at(i, j, ComponentID(0), false)) { case 0: rowShift = 1; colShift = 0; break; case 45: rowShift = 1; colShift = 1; break; case 90: rowShift = 0; colShift = 1; break; case 135: rowShift = -1; colShift = 1; break; default: throw("Unsupported gradient direction."); break; } Pel pelCurrent = buff1->at(i, j, compID, false); Pel pelEdgeDirectionTop = buff1->at(i + rowShift, j + colShift, compID, false); Pel pelEdgeDirectionBottom = buff1->at(i - rowShift, j - colShift, compID, false); if ((pelCurrent < pelEdgeDirectionTop) || (pelCurrent < pelEdgeDirectionBottom)) { buff2->at(i, j, ComponentID(0), false) = 0; // supress } else { buff2->at(i, j, ComponentID(0), false) = buff1->at(i, j, compID, false); // keep } } } buff2->copyTo(buff1, ComponentID(0), compID, false, false); } void Canny::doubleThreshold(TComPicYuv* buff, unsigned int width, unsigned int height, /*unsigned int windowSizeRatio,*/ unsigned int bitDepth, ComponentID compID) { Pel strongPel = ((Pel) 1 << bitDepth) - 1; Pel weekPel = ((Pel) 1 << (bitDepth - 1)) - 1; Pel highThreshold = 0; Pel lowThreshold = strongPel; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { highThreshold = std::max(highThreshold, buff->at(i, j, compID, false)); } } // global low and high threshold lowThreshold = (Pel)(m_lowThresholdRatio * highThreshold); highThreshold = Clip3(0, (1 << bitDepth) - 1, m_highThresholdRatio * lowThreshold); // Canny recommended a upper:lower ratio between 2:1 and 3:1. // strong, week, supressed for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (buff->at(i, j, compID, false) > highThreshold) buff->at(i, j, compID, false) = strongPel; else if (buff->at(i, j, compID, false) <= highThreshold && buff->at(i, j, compID, false) > lowThreshold) buff->at(i, j, compID, false) = weekPel; else buff->at(i, j, compID, false) = 0; } } buff->extendPicBorder(compID, 1, 1, false); // extend one pixel on each side for the next step } void Canny::edgeTracking(TComPicYuv* buff, unsigned int width, unsigned int height, unsigned int windowWidth, unsigned int windowHeight, unsigned int bitDepth, ComponentID compID) { Pel strongPel = ((Pel) 1 << bitDepth) - 1; Pel weekPel = ((Pel) 1 << (bitDepth - 1)) - 1; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (buff->at(i, j, compID, false) == weekPel) { bool strong = false; for (int x = 0; x < windowWidth; x++) { for (int y = 0; y < windowHeight; y++) { if (buff->at(x - windowWidth / 2 + i, y - windowHeight / 2 + j, compID, false) == strongPel) { strong = true; break; } } } if (strong) { buff->at(i, j, compID, false) = strongPel; } else { buff->at(i, j, compID, false) = 0; // supress } } } } } void Canny::detect_edges(const TComPicYuv* orig, TComPicYuv* dest, unsigned int uiBitDepth, ComponentID compID) { /* No noise reduction - Gaussian blur is skipped; Gradient calculation; Non-maximum suppression; Double threshold; Edge Tracking by Hysteresis.*/ const int width = orig->getWidth(compID); const int height = orig->getHeight(compID); unsigned int convWidthS = m_convWidthS, convHeightS = m_convHeightS; // Pixel's row and col positions for Sobel filtering unsigned int bitDepth = uiBitDepth; // tmp buff TComPicYuv* orientationBuf = new TComPicYuv; orientationBuf->createWithPadding(width, height, CHROMA_400); orig->copyTo(dest, compID, compID, false, false); /* Gradient calculation */ gradient(dest, orientationBuf, width, height, convWidthS, convHeightS, bitDepth, compID); /* Non - maximum suppression */ suppressNonMax(dest, orientationBuf, width, height, compID); /* Double threshold */ doubleThreshold(dest, width, height, /*4,*/ bitDepth, compID); /* Edge Tracking by Hysteresis */ edgeTracking(dest, width, height, convWidthS, convHeightS, bitDepth, compID); orientationBuf->destroy(); delete orientationBuf; orientationBuf = nullptr; } // ==================================================================================================================== // Morphologigal operations - Dilation and Erosion // ==================================================================================================================== Morph::Morph() { // init(); } Morph::~Morph() { // uninit(); } int Morph::dilation(TComPicYuv* buff, unsigned int bitDepth, ComponentID compID, int numIter, int iter) { if (iter == numIter) return iter; const int width = buff->getWidth(compID); const int height = buff->getHeight(compID); unsigned int windowSize = m_kernelSize; unsigned int padding = windowSize / 2; Pel strongPel = ((Pel) 1 << bitDepth) - 1; TComPicYuv* tmpBuf = new TComPicYuv; tmpBuf->createWithPadding(width, height, CHROMA_400); buff->copyTo(tmpBuf, compID, ComponentID(0), false, false); buff->extendPicBorder(compID, padding, padding, false); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { bool strong = false; for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { if (buff->at(x - windowSize / 2 + i, y - windowSize / 2 + j, compID, false) == strongPel) { strong = true; break; } } } if (strong) { tmpBuf->at(i, j, ComponentID(0), false) = strongPel; } } } tmpBuf->copyTo(buff, ComponentID(0), compID, false, false); tmpBuf->destroy(); delete tmpBuf; tmpBuf = nullptr; iter++; iter = dilation(buff, bitDepth, compID, numIter, iter); return iter; } int Morph::erosion(TComPicYuv* buff, unsigned int bitDepth, ComponentID compID, int numIter, int iter) { if (iter == numIter) return iter; const int width = buff->getWidth(compID); const int height = buff->getHeight(compID); unsigned int windowSize = m_kernelSize; unsigned int padding = windowSize / 2; TComPicYuv* tmpBuf = new TComPicYuv; tmpBuf->createWithPadding(width, height, CHROMA_400); buff->copyTo(tmpBuf, compID, ComponentID(0), false, false); buff->extendPicBorder(compID, padding, padding, false); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { bool week = false; for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { if (buff->at(x - windowSize / 2 + i, y - windowSize / 2 + j, compID, false) == 0) { week = true; break; } } } if (week) { tmpBuf->at(i, j, ComponentID(0), false) = 0; } } } tmpBuf->copyTo(buff, ComponentID(0), compID, false, false); tmpBuf->destroy(); delete tmpBuf; tmpBuf = nullptr; iter++; iter = erosion(buff, bitDepth, compID, numIter, iter); return iter; } // ==================================================================================================================== // Film Grain Analysis Functions // ==================================================================================================================== FGAnalyser::FGAnalyser() { // init(); } FGAnalyser::~FGAnalyser() { // uninit(); } // initialize film grain parameters void FGAnalyser::init(const int width, const int height, const int sourcePaddingWidth, const int sourcePaddingHeight, const InputColourSpaceConversion ipCSC, bool bClipInputVideoToRec709Range, const ChromaFormat inputChroma, const BitDepths& inputBitDepths, const BitDepths& outputBitDepths, const int frameSkip, const bool doAnalysis[], std::string filmGrainExternalMask, std::string filmGrainExternalDenoised) { m_log2ScaleFactor = 2; for (int i = 0; i < MAX_NUM_COMPONENT; i++) { m_compModel[i].bPresentFlag = true; m_compModel[i].numModelValues = 1; m_compModel[i].numIntensityIntervals = 1; m_compModel[i].intensityValues.resize(FG_MAX_NUM_INTENSITIES); for (int j = 0; j < FG_MAX_NUM_INTENSITIES; j++) { m_compModel[i].intensityValues[j].intensityIntervalLowerBound = 10; m_compModel[i].intensityValues[j].intensityIntervalUpperBound = 250; m_compModel[i].intensityValues[j].compModelValue.resize(FG_MAX_ALLOWED_MODEL_VALUES); for (int k = 0; k < m_compModel[i].numModelValues; k++) { m_compModel[i].intensityValues[j].compModelValue[k] = 26 - 13 * (toChannelType((ComponentID) i)); // half intensity for chroma. Provided value is default value, manually tuned. } } m_doAnalysis[i] = doAnalysis[i]; } // initialize picture parameters and create buffers m_chromaFormatIDC = inputChroma; m_bitDepthsIn = inputBitDepths; m_bitDepths = outputBitDepths; m_sourcePadding[0] = sourcePaddingWidth; m_sourcePadding[1] = sourcePaddingHeight; m_ipCSC = ipCSC; m_bClipInputVideoToRec709Range = bClipInputVideoToRec709Range; m_frameSkip = frameSkip; m_filmGrainExternalMask = filmGrainExternalMask; m_filmGrainExternalDenoised = filmGrainExternalDenoised; int margin = m_edgeDetector.m_convWidthG / 2; // set margin for padding for filtering if (!m_originalBuf) { m_originalBuf = new TComPicYuv; m_originalBuf->createWithPadding(width, height, inputChroma, true, false, margin, margin); } if (!m_workingBuf) { m_workingBuf = new TComPicYuv; m_workingBuf->createWithPadding(width, height, inputChroma, true, false, margin, margin); } if (!m_maskBuf) { m_maskBuf = new TComPicYuv; m_maskBuf->createWithPadding(width, height, inputChroma, true, false, margin, margin); } } // initialize buffers with real data bool FGAnalyser::initBufs(TComPic *pic) { pic->getPicYuvTrueOrg()->copyToPic(m_originalBuf, true, false); // original is here TComPicYuv dummyPicBufferTO; // Only used temporary in yuvFrames.read dummyPicBufferTO.createWithoutCUInfo(m_workingBuf->getWidth(COMPONENT_Y), m_workingBuf->getHeight(COMPONENT_Y), m_chromaFormatIDC, true, m_sourcePadding[0], m_sourcePadding[1]); //dummyPicBufferTO.create(pic->cs->area); if (!m_filmGrainExternalDenoised.empty()) // read external denoised frame { TVideoIOYuv yuvFrames; yuvFrames.open(m_filmGrainExternalDenoised, false, m_bitDepthsIn.recon, m_bitDepthsIn.recon, m_bitDepths.recon); yuvFrames.skipFrames(pic->getPOC() + m_frameSkip, m_workingBuf->getWidth(COMPONENT_Y) - m_sourcePadding[0], m_workingBuf->getHeight(COMPONENT_Y) - m_sourcePadding[1], m_chromaFormatIDC); if (!yuvFrames.read(m_workingBuf, &dummyPicBufferTO, m_ipCSC, m_sourcePadding, m_chromaFormatIDC, m_bClipInputVideoToRec709Range)) { return false; // eof or read fail } yuvFrames.close(); } else // use mctf denoised frame for film grain analysis. note: if mctf is used, it is different from mctf for encoding. { pic->getPicFilteredFG()->copyToPic(m_workingBuf); // mctf filtered frame for film grain analysis is in here } if (!m_filmGrainExternalMask.empty()) // read external mask { TVideoIOYuv yuvFrames; yuvFrames.open(m_filmGrainExternalMask, false, m_bitDepthsIn.recon, m_bitDepthsIn.recon, m_bitDepths.recon); yuvFrames.skipFrames(pic->getPOC() + m_frameSkip, m_maskBuf->getWidth(COMPONENT_Y) - m_sourcePadding[0], m_maskBuf->getHeight(COMPONENT_Y) - m_sourcePadding[1], m_chromaFormatIDC); if (!yuvFrames.read(m_maskBuf, &dummyPicBufferTO, m_ipCSC, m_sourcePadding, m_chromaFormatIDC, m_bClipInputVideoToRec709Range)) { return false; // eof or read fail } yuvFrames.close(); } else // find mask { findMask(); } return true; } // delete picture buffers void FGAnalyser::destroy() { if (m_originalBuf != nullptr) { m_originalBuf->destroy(); delete m_originalBuf; m_originalBuf = nullptr; } if (m_workingBuf != nullptr) { m_workingBuf->destroy(); delete m_workingBuf; m_workingBuf = nullptr; } if (m_maskBuf != nullptr) { m_maskBuf->destroy(); delete m_maskBuf; m_maskBuf = nullptr; } } // main functions for film grain analysis void FGAnalyser::estimate_grain(TComPic*pic) { // estimate parameters estimate_grain_parameters(); } // find flat and low complexity regions of the frame void FGAnalyser::findMask() { const int width = m_workingBuf->getWidth(COMPONENT_Y); const int height = m_workingBuf->getHeight(COMPONENT_Y); const int newWidth2 = m_workingBuf->getWidth(COMPONENT_Y) / 2; const int newHeight2 = m_workingBuf->getHeight(COMPONENT_Y) / 2; const int newWidth4 = m_workingBuf->getWidth(COMPONENT_Y) / 4; const int newHeight4 = m_workingBuf->getHeight(COMPONENT_Y) / 4; const unsigned padding = m_edgeDetector.m_convWidthG / 2; // for filtering // create tmp buffs TComPicYuv* workingBufSubsampled2 = new TComPicYuv; TComPicYuv* maskSubsampled2 = new TComPicYuv; TComPicYuv* workingBufSubsampled4 = new TComPicYuv; TComPicYuv* maskSubsampled4 = new TComPicYuv; TComPicYuv* maskUpsampled = new TComPicYuv; workingBufSubsampled2->createWithPadding(newWidth2, newHeight2, m_workingBuf->getChromaFormat(), true, false, padding, padding); maskSubsampled2->createWithPadding(newWidth2, newHeight2, m_workingBuf->getChromaFormat(), true, false, padding, padding); workingBufSubsampled4->createWithPadding(newWidth4, newHeight4, m_workingBuf->getChromaFormat(), true, false, padding, padding); maskSubsampled4->createWithPadding(newWidth4, newHeight4, m_workingBuf->getChromaFormat(), true, false, padding, padding); maskUpsampled->createWithPadding(width, height, m_workingBuf->getChromaFormat(), true, false, padding, padding); for (int compIdx = 0; compIdx < getNumberValidComponents(m_chromaFormatIDC); compIdx++) { ComponentID compID = ComponentID(compIdx); ChannelType channelId = toChannelType(compID); int bitDepth = m_bitDepths[channelId]; if (!m_doAnalysis[compID]) continue; // subsample original picture subsample(*m_workingBuf, *workingBufSubsampled2, compID, 2, padding); subsample(*m_workingBuf, *workingBufSubsampled4, compID, 4, padding); // full resolution m_edgeDetector.detect_edges(m_workingBuf, m_maskBuf, bitDepth, compID); suppressLowIntensity(*m_workingBuf, *m_maskBuf, bitDepth, compID); m_morphOperation.dilation(m_maskBuf, bitDepth, compID, 4); // subsampled 2 m_edgeDetector.detect_edges(workingBufSubsampled2, maskSubsampled2, bitDepth, compID); suppressLowIntensity(*workingBufSubsampled2, *maskSubsampled2, bitDepth, compID); m_morphOperation.dilation(maskSubsampled2, bitDepth, compID, 3); // upsample, combine maskBuf and maskUpsampled upsample(*maskSubsampled2, *maskUpsampled, compID, 2); combineMasks(*m_maskBuf, *maskUpsampled, compID); // subsampled 4 m_edgeDetector.detect_edges(workingBufSubsampled4, maskSubsampled4, bitDepth, compID); suppressLowIntensity(*workingBufSubsampled4, *maskSubsampled4, bitDepth, compID); m_morphOperation.dilation(maskSubsampled4, bitDepth, compID, 2); // upsample, combine maskBuf and maskUpsampled upsample(*maskSubsampled4, *maskUpsampled, compID, 4); combineMasks(*m_maskBuf, *maskUpsampled, compID); // final dilation to fill the holes + same number of erosion m_morphOperation.dilation(m_maskBuf, bitDepth, compID, 2); m_morphOperation.erosion(m_maskBuf, bitDepth, compID, 1); } workingBufSubsampled2->destroy(); maskSubsampled2->destroy(); workingBufSubsampled4->destroy(); maskSubsampled4->destroy(); maskUpsampled->destroy(); delete workingBufSubsampled2; workingBufSubsampled2 = nullptr; delete maskSubsampled2; maskSubsampled2 = nullptr; delete workingBufSubsampled4; workingBufSubsampled4 = nullptr; delete maskSubsampled4; maskSubsampled4 = nullptr; delete maskUpsampled; maskUpsampled = nullptr; } void FGAnalyser::suppressLowIntensity(const TComPicYuv& buff1, TComPicYuv& buff2, unsigned int bitDepth, ComponentID compID) { // buff1 - intensity values ( luma or chroma samples); buff2 - mask const int width = buff2.getWidth(compID); const int height = buff2.getHeight(compID); Pel maxIntensity = ((Pel) 1 << bitDepth) - 1; Pel lowIntensityThreshold = (Pel)(m_lowIntensityRatio * maxIntensity); // strong, week, supressed for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (buff1.at(i, j, compID, false) < lowIntensityThreshold) buff2.at(i, j, compID, false) = maxIntensity; } } } void FGAnalyser::subsample(const TComPicYuv& input, TComPicYuv& output, ComponentID compID, const int factor, const int padding) const { const int newWidth = input.getWidth(compID) / factor; const int newHeight = input.getHeight(compID) / factor; const Pel *srcRow = input.getAddr(compID); const int srcStride = input.getStride(compID,false); Pel * dstRow = output.getAddr(compID); const int dstStride = output.getStride(compID,false); for (int y = 0; y < newHeight; y++, srcRow += factor * srcStride, dstRow += dstStride) { const Pel *inRow = srcRow; const Pel *inRowBelow = srcRow + srcStride; Pel * target = dstRow; for (int x = 0; x < newWidth; x++) { target[x] = (inRow[0] + inRowBelow[0] + inRow[1] + inRowBelow[1] + 2) >> 2; inRow += factor; inRowBelow += factor; } } if (padding) { output.extendPicBorder(compID, padding, padding, false); } } void FGAnalyser::upsample(const TComPicYuv& input, TComPicYuv& output, ComponentID compID, const int factor, const int padding) const { // binary mask upsampling // use simple replication of pixels const int width = input.getWidth(compID); const int height = input.getHeight(compID); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { Pel currentPel = input.at(i, j, compID, false); for (int x = 0; x < factor; x++) { for (int y = 0; y < factor; y++) { output.at(i * factor + x, j * factor + y, compID, false) = currentPel; } } } } if (padding) { output.extendPicBorder(compID, padding, padding, false); } } void FGAnalyser::combineMasks(TComPicYuv& buff1, TComPicYuv& buff2, ComponentID compID) { const int width = buff1.getWidth(compID); const int height = buff1.getHeight(compID); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { buff1.at(i, j, compID, false) = (buff1.at(i, j, compID, false) | buff2.at(i, j, compID, false)); } } } // estimate cut-off frequencies and scaling factors for different intensity intervals void FGAnalyser::estimate_grain_parameters() { TComPicYuv* tmpBuff = new TComPicYuv; // tmpBuff is diference between original and filtered => film grain estimate tmpBuff->createWithPadding(m_workingBuf->getWidth(ComponentID(0)), m_workingBuf->getHeight(ComponentID(0)), m_workingBuf->getChromaFormat()); m_workingBuf->copyToPic(tmpBuff, false, false); // workingBuf is filtered image subtract(*m_originalBuf, *tmpBuff); // find difference between original and filtered/reconstructed frame => film grain estimate int blockSize = FG_BLK_8; uint32_t picSizeInLumaSamples = m_workingBuf->getHeight(ComponentID(0)) * m_workingBuf->getWidth(ComponentID(0)); if (picSizeInLumaSamples <= (1920 * 1080)) { blockSize = FG_BLK_8; } else if (picSizeInLumaSamples <= (3840 * 2160)) { blockSize = FG_BLK_16; } else { blockSize = FG_BLK_32; } for (int compIdx = 0; compIdx < getNumberValidComponents(m_chromaFormatIDC); compIdx++) { // loop over components ComponentID compID = ComponentID(compIdx); ChannelType channelId = toChannelType(compID); if (!m_doAnalysis[compID]) continue; unsigned int width = m_workingBuf->getWidth(compID); // Width of current frame unsigned int height = m_workingBuf->getHeight(compID); // Height of current frame unsigned int windowSize = FG_DATA_BASE_SIZE; // Size for Film Grain block int bitDepth = m_bitDepths[channelId]; int detect_edges = 0; int mean = 0; int var = 0; std::vector vec_mean; std::vector vec_var; std::vector squared_dct_grain_block_list; for (int i = 0; i <= width - windowSize; i += windowSize) { // loop over windowSize x windowSize blocks for (int j = 0; j <= height - windowSize; j += windowSize) { detect_edges = count_edges(*m_maskBuf, windowSize, compID, i, j); // for flat region without edges if (detect_edges) // selection of uniform, flat and low-complexity area; extend to other features, e.g., variance. { // find transformed blocks; cut-off frequency estimation is done on 64 x 64 blocks as low-pass filtering on synthesis side is done on 64 x 64 blocks. block_transform(*tmpBuff, squared_dct_grain_block_list, i, j, bitDepth, compID); } int step = windowSize / blockSize; for (int k = 0; k < step; k++) { for (int m = 0; m < step; m++) { detect_edges = count_edges(*m_maskBuf, blockSize, compID, i + k * blockSize, j + m * blockSize); // for flat region without edges if (detect_edges) // selection of uniform, flat and low-complexity area; extend to other features, e.g., variance. { // collect all data for parameter estimation; mean and variance are caluclated on blockSize x blockSize blocks mean = meanVar(*m_workingBuf, blockSize, compID, i + k * blockSize, j + m * blockSize, false); var = meanVar(*tmpBuff, blockSize, compID, i + k * blockSize, j + m * blockSize, true); // regularize high variations; controls excessively fluctuating points double tmp = 3.0 * pow((double)(var), .5) + .5; var = (int)tmp; if (var < (MAX_REAL_SCALE << (bitDepth - FG_BIT_DEPTH_8))) // limit data points to meaningful values. higher variance can be result of not perfect mask estimation (non-flat regions fall in estimation process) { vec_mean.push_back(mean); // mean of the filtered frame vec_var.push_back(var); // variance of the film grain estimate } } } } } } // calculate film grain parameters estimate_cutoff_freq(squared_dct_grain_block_list, compID); estimate_scaling_factors(vec_mean, vec_var, bitDepth, compID); } tmpBuff->destroy(); delete tmpBuff; tmpBuff = nullptr; } // find compModelValue[0] - different scaling based on the pixel intensity void FGAnalyser::estimate_scaling_factors(std::vector &data_x, std::vector &data_y, unsigned int bitDepth, ComponentID compID) { if (!m_compModel[compID].bPresentFlag || data_x.size() < MIN_POINTS_FOR_INTENSITY_ESTIMATION) // if cutoff frequencies are not estimated previously, do not proceed since presentFlag is set to false in a previous step return; // also if there is no enough points to estimate film grain intensities, default or previously estimated parameters are used // estimate intensity regions std::vector coeffs; std::vector scalingVec; std::vector quantVec; double distortion = 0.0; // Fit the points with the curve. Quantization of the curve using Lloyd Max quantization. bool valid; for (int i = 0; i < NUM_PASSES; i++) // if num_passes = 2, filtering of the dataset points is performed { valid = fit_function(data_x, data_y, coeffs, scalingVec, ORDER, bitDepth, i); // n-th order polynomial regression for scaling function estimation if (!valid) break; } if (valid) { avg_scaling_vec(scalingVec, compID, bitDepth); // scale with previously fitted function to smooth the intensity valid = lloyd_max(scalingVec, quantVec, distortion, QUANT_LEVELS, bitDepth); // train quantizer and quantize curve using Lloyd Max } // Based on quantized intervals, set intensity region and scaling parameter if (valid) // if not valid, reuse previous parameters (for example, if var is all zero) setEstimatedParameters(quantVec, bitDepth, compID); } // Horizontal and Vertical cutoff frequencies estimation. Assumption is that for complete sequence there is only one set of the cut-off frequencies (implementation decision) void FGAnalyser::estimate_cutoff_freq(const std::vector &blocks, ComponentID compID) { PelMatrixDouble mean_squared_dct_grain(FG_DATA_BASE_SIZE, std::vector(FG_DATA_BASE_SIZE)); vector vec_mean_dct_grain_row(FG_DATA_BASE_SIZE, 0.0); vector vec_mean_dct_grain_col(FG_DATA_BASE_SIZE, 0.0); static bool isFirstCutoffEst[MAX_NUM_COMPONENT] = {true, true, true }; int num_blocks = (int) blocks.size(); if (num_blocks < MIN_BLOCKS_FOR_CUTOFF_ESTIMATION) // if there is no enough 64 x 64 blocks to estimate cut-off freq, skip cut-off freq estimation and use previous parameters return; // iterate over the block and find avarage block for (int x = 0; x < FG_DATA_BASE_SIZE; x++) { for (int y = 0; y < FG_DATA_BASE_SIZE; y++) { for (const auto &dct_grain_block: blocks) { mean_squared_dct_grain[x][y] += dct_grain_block[x][y]; } mean_squared_dct_grain[x][y] /= num_blocks; // Computation of horizontal and vertical mean vector (DC component is skipped) vec_mean_dct_grain_row[x] += ((x != 0) && (y != 0)) ? mean_squared_dct_grain[x][y] : 0.0; vec_mean_dct_grain_col[y] += ((x != 0) && (y != 0)) ? mean_squared_dct_grain[x][y] : 0.0; } } for (int x = 0; x < FG_DATA_BASE_SIZE; x++) { vec_mean_dct_grain_row[x] /= (x == 0) ? FG_DATA_BASE_SIZE - 1 : FG_DATA_BASE_SIZE; vec_mean_dct_grain_col[x] /= (x == 0) ? FG_DATA_BASE_SIZE - 1 : FG_DATA_BASE_SIZE; } int cutoff_vertical = cutoff_frequency(vec_mean_dct_grain_row); int cutoff_horizontal = cutoff_frequency(vec_mean_dct_grain_col); if (cutoff_vertical && cutoff_horizontal) { m_compModel[compID].bPresentFlag = true; m_compModel[compID].numModelValues = 1; } else { m_compModel[compID].bPresentFlag = false; } if (m_compModel[compID].bPresentFlag) { if (isFirstCutoffEst[compID]) // to avoid averaging with default { m_compModel[compID].intensityValues[0].compModelValue[1] = cutoff_horizontal; m_compModel[compID].intensityValues[0].compModelValue[2] = cutoff_vertical; isFirstCutoffEst[compID] = false; } else { m_compModel[compID].intensityValues[0].compModelValue[1] = (m_compModel[compID].intensityValues[0].compModelValue[1] + cutoff_horizontal + 1) / 2; m_compModel[compID].intensityValues[0].compModelValue[2] = (m_compModel[compID].intensityValues[0].compModelValue[2] + cutoff_vertical + 1) / 2; } if (m_compModel[compID].intensityValues[0].compModelValue[1] != 8 || m_compModel[compID].intensityValues[0].compModelValue[2] != 8) // default is 8 m_compModel[compID].numModelValues++; if (m_compModel[compID].intensityValues[0].compModelValue[1] != m_compModel[compID].intensityValues[0].compModelValue[2]) m_compModel[compID].numModelValues++; } } int FGAnalyser::cutoff_frequency(std::vector &mean) { std::vector sum(FG_DATA_BASE_SIZE, 0.0); // Regularize the curve to suppress peaks mean.push_back(mean.back()); mean.insert(mean.begin(), mean.front()); for (int j = 1; j < FG_DATA_BASE_SIZE + 1; j++) { sum[j - 1] = (m_tap_filtar[0] * mean[j - 1] + m_tap_filtar[1] * mean[j] + m_tap_filtar[2] * mean[j + 1]) / m_normTap; } double target = 0; for (int j = 0; j < FG_DATA_BASE_SIZE; j++) target += sum[j]; target /= FG_DATA_BASE_SIZE; // find final cut-off frequency std::vector intersectionPointList; for (int x = 0; x < FG_DATA_BASE_SIZE - 1; x++) { if ((target < sum[x] && target >= sum[x + 1]) || (target > sum[x] && target <= sum[x + 1])) { // there is intersection double first_point = fabs(target - sum[x]); double second_point = fabs(target - sum[x + 1]); if (first_point < second_point) { intersectionPointList.push_back(x); } else { intersectionPointList.push_back(x + 1); } } } int size = (int) intersectionPointList.size(); if (size > 0) { return Clip3(2, 14, (intersectionPointList[size - 1] - 1) >> 2); // clip to RDD5 range, (h-3)/4 + 0.5 } else { return 0; } } // DCT-2 64x64 as defined in VVC void FGAnalyser::block_transform(const TComPicYuv& buff, std::vector &squared_dct_grain_block_list, int offsetX, int offsetY, unsigned int bitDepth, ComponentID compID) { unsigned int windowSize = FG_DATA_BASE_SIZE; // Size for Film Grain block Intermediate_Int max_dynamic_range = (1 << (bitDepth + 6)) - 1; // Dynamic range after DCT transform for 64x64 block Intermediate_Int min_dynamic_range = -((1 << (bitDepth + 6)) - 1); Intermediate_Int sum; const TMatrixCoeff *tmp = g_aiT64[TRANSFORM_FORWARD][0]; const int transform_scale = 9; // upscaling of original transform as specified in VVC (for 64x64 block) const int add_1st = 1 << (transform_scale - 1); TMatrixCoeff tr[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; // Original TMatrixCoeff trt[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; // Transpose for (int x = 0; x < FG_DATA_BASE_SIZE; x++) { for (int y = 0; y < FG_DATA_BASE_SIZE; y++) { tr[x][y] = tmp[x * 64 + y]; /* Matrix Original */ trt[y][x] = tmp[x * 64 + y]; /* Matrix Transpose */ } } // DCT transform PelMatrix blockDCT(windowSize, std::vector(windowSize)); PelMatrix blockTmp(windowSize, std::vector(windowSize)); for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { sum = 0; for (int k = 0; k < windowSize; k++) { sum += tr[x][k] * buff.at(offsetX + k, offsetY + y, compID, false); } blockTmp[x][y] = (sum + add_1st) >> transform_scale; } } for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { sum = 0; for (int k = 0; k < windowSize; k++) { sum += blockTmp[x][k] * trt[k][y]; } blockDCT[x][y] = Clip3(min_dynamic_range, max_dynamic_range, (sum + add_1st) >> transform_scale); } } for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { blockDCT[x][y] = blockDCT[x][y] * blockDCT[x][y]; } } // store squared transformed block for further analysis squared_dct_grain_block_list.push_back(blockDCT); } // check edges int FGAnalyser::count_edges(TComPicYuv& buffer, int windowSize, ComponentID compID, int offsetX, int offsetY) { for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { if (buffer.at(offsetX + x, offsetY + y, compID, false)) { return 0; } } } return 1; } // calulate mean and variance for windowSize x windowSize block int FGAnalyser::meanVar(TComPicYuv& buffer, int windowSize, ComponentID compID, int offsetX, int offsetY, bool getVar) { double m = 0, v = 0; for (int x = 0; x < windowSize; x++) { for (int y = 0; y < windowSize; y++) { m += buffer.at(offsetX + x, offsetY + y, compID, false); v += (buffer.at(offsetX + x, offsetY + y, compID, false) * buffer.at(offsetX + x, offsetY + y, compID, false)); } } m = m / (windowSize * windowSize); if (getVar) { return (int)(v / (windowSize * windowSize) - m * m + .5); } return (int)(m + .5); } // Fit data to a function using n-th order polynomial interpolation bool FGAnalyser::fit_function(std::vector &data_x, std::vector &data_y, std::vector &coeffs, std::vector &scalingVec, int order, int bitDepth, bool second_pass) { PelMatrixLongDouble a(MAXPAIRS + 1, std::vector(MAXPAIRS + 1)); PelVectorLongDouble B(MAXPAIRS + 1), C(MAXPAIRS + 1), S(MAXPAIRS + 1); long double A1, A2, Y1, m, S1, x1; long double xscale, yscale; long double xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0; long double polycoefs[MAXORDER + 1]; int i, j, k, L, R; // several data filtering and data manipulations before fitting the function // create interval points for function fitting int INTENSITY_INTERVAL_NUMBER = (1 << bitDepth) / INTERVAL_SIZE; std::vector vec_mean_intensity(INTENSITY_INTERVAL_NUMBER, 0); std::vector vec_variance_intensity(INTENSITY_INTERVAL_NUMBER, 0); std::vector element_number_per_interval(INTENSITY_INTERVAL_NUMBER, 0); std::vector tmp_data_x; std::vector tmp_data_y; double mn = 0.0, sd = 0.0; if (second_pass) // in second pass, filter based on the variance of the data_y. remove all high and low points { xmin = scalingVec.back(); scalingVec.pop_back(); xmax = scalingVec.back(); scalingVec.pop_back(); int n = (int) data_y.size(); if (n != 0) { mn = accumulate(data_y.begin(), data_y.end(), 0.0) / n; for (int cnt = 0; cnt < n; cnt++) { sd += (data_y[cnt] - mn) * (data_y[cnt] - mn); } sd /= n; sd = sqrt(sd); } } for (int cnt = 0; cnt < data_x.size(); cnt++) { if (second_pass) { if (data_x[cnt] >= xmin && data_x[cnt] <= xmax) { if ((data_y[cnt] < scalingVec[data_x[cnt] - (int) xmin] + sd * VAR_SCALE_UP) && (data_y[cnt] > scalingVec[data_x[cnt] - (int) xmin] - sd * VAR_SCALE_DOWN)) { int block_index = data_x[cnt] / INTERVAL_SIZE; vec_mean_intensity[block_index] += data_x[cnt]; vec_variance_intensity[block_index] += data_y[cnt]; element_number_per_interval[block_index]++; } } } else { int block_index = data_x[cnt] / INTERVAL_SIZE; vec_mean_intensity[block_index] += data_x[cnt]; vec_variance_intensity[block_index] += data_y[cnt]; element_number_per_interval[block_index]++; } } // create a points per intensity interval for (int block_idx = 0; block_idx < INTENSITY_INTERVAL_NUMBER; block_idx++) { if (element_number_per_interval[block_idx] >= MIN_ELEMENT_NUMBER_PER_INTENSITY_INTERVAL) { tmp_data_x.push_back(vec_mean_intensity[block_idx] / element_number_per_interval[block_idx]); tmp_data_y.push_back(vec_variance_intensity[block_idx] / element_number_per_interval[block_idx]); } } // There needs to be at least ORDER+1 points to fit the function if (tmp_data_x.size() < (order + 1)) return false; // if there is no enough blocks to estimate film grain parameters, default or previously estimated parameters are used for (i = 0; i < tmp_data_x.size(); i++) // remove single points before extending and fitting { int check = 0; for (j = -WINDOW; j <= WINDOW; j++) { int idx = i + j; if (idx >= 0 && idx < tmp_data_x.size() && j != 0) { check += abs(tmp_data_x[i] / INTERVAL_SIZE - tmp_data_x[idx] / INTERVAL_SIZE) <= WINDOW ? 1 : 0; } } if (check < NBRS) { tmp_data_x.erase(tmp_data_x.begin() + i); tmp_data_y.erase(tmp_data_y.begin() + i); i--; } } extend_points(tmp_data_x, tmp_data_y, bitDepth); // find the most left and the most right point, and extend edges // fitting the function starts here xmin = tmp_data_x[0]; xmax = tmp_data_x[0]; ymin = tmp_data_y[0]; ymax = tmp_data_y[0]; for (i = 0; i < tmp_data_x.size(); i++) { if (tmp_data_x[i] < xmin) xmin = tmp_data_x[i]; if (tmp_data_x[i] > xmax) xmax = tmp_data_x[i]; if (tmp_data_y[i] < ymin) ymin = tmp_data_y[i]; if (tmp_data_y[i] > ymax) ymax = tmp_data_y[i]; } long double xlow = xmax; long double ylow = ymax; int data_pairs = (int) tmp_data_x.size(); PelMatrixDouble data_array(2, std::vector(MAXPAIRS + 1)); for (i = 0; i < data_pairs; i++) { data_array[0][i + 1] = (double) tmp_data_x[i]; data_array[1][i + 1] = (double) tmp_data_y[i]; } // release memory for data_x and data_y, and clear previous vectors vector().swap(tmp_data_x); vector().swap(tmp_data_y); if (second_pass) { vector().swap(data_x); vector().swap(data_y); vector().swap(coeffs); vector().swap(scalingVec); } for (i = 1; i <= data_pairs; i++) { if (data_array[0][i] < xlow && data_array[0][i] != 0) xlow = data_array[0][i]; if (data_array[1][i] < ylow && data_array[1][i] != 0) ylow = data_array[1][i]; } if (xlow < .001 && xmax < 1000) xscale = 1 / xlow; else if (xmax > 1000 && xlow > .001) xscale = 1 / xmax; else xscale = 1; if (ylow < .001 && ymax < 1000) yscale = 1 / ylow; else if (ymax > 1000 && ylow > .001) yscale = 1 / ymax; else yscale = 1; // initialise array variables for (i = 0; i <= MAXPAIRS; i++) { B[i] = 0; C[i] = 0; S[i] = 0; for (j = 0; j < MAXPAIRS; j++) a[i][j] = 0; } for (i = 0; i <= MAXORDER; i++) polycoefs[i] = 0; Y1 = 0; for (j = 1; j <= data_pairs; j++) { for (i = 1; i <= order; i++) { B[i] = B[i] + data_array[1][j] * yscale * ldpow(data_array[0][j] * xscale, i); if (B[i] == std::numeric_limits::max()) return false; for (k = 1; k <= order; k++) { a[i][k] = a[i][k] + ldpow(data_array[0][j] * xscale, (i + k)); if (a[i][k] == std::numeric_limits::max()) return false; } S[i] = S[i] + ldpow(data_array[0][j] * xscale, i); if (S[i] == std::numeric_limits::max()) return false; } Y1 = Y1 + data_array[1][j] * yscale; if (Y1 == std::numeric_limits::max()) return false; } for (i = 1; i <= order; i++) { for (j = 1; j <= order; j++) { a[i][j] = a[i][j] - S[i] * S[j] / (long double) data_pairs; if (a[i][j] == std::numeric_limits::max()) return false; } B[i] = B[i] - Y1 * S[i] / (long double) data_pairs; if (B[i] == std::numeric_limits::max()) return false; } for (k = 1; k <= order; k++) { R = k; A1 = 0; for (L = k; L <= order; L++) { A2 = fabsl(a[L][k]); if (A2 > A1) { A1 = A2; R = L; } } if (A1 == 0) return false; if (R == k) goto polfit1; for (j = k; j <= order; j++) { x1 = a[R][j]; a[R][j] = a[k][j]; a[k][j] = x1; } x1 = B[R]; B[R] = B[k]; B[k] = x1; polfit1: for (i = k; i <= order; i++) { m = a[i][k]; for (j = k; j <= order; j++) { if (i == k) a[i][j] = a[i][j] / m; else a[i][j] = a[i][j] - m * a[k][j]; } if (i == k) B[i] = B[i] / m; else B[i] = B[i] - m * B[k]; } } polycoefs[order] = B[order]; for (k = 1; k <= order - 1; k++) { i = order - k; S1 = 0; for (j = 1; j <= order; j++) { S1 = S1 + a[i][j] * polycoefs[j]; if (S1 == std::numeric_limits::max()) return false; } polycoefs[i] = B[i] - S1; } S1 = 0; for (i = 1; i <= order; i++) { S1 = S1 + polycoefs[i] * S[i] / (long double) data_pairs; if (S1 == std::numeric_limits::max()) return false; } polycoefs[0] = (Y1 / (long double) data_pairs - S1); // zero all coeficient values smaller than +/- .00000000001 (avoids -0) for (i = 0; i <= order; i++) if (fabsl(polycoefs[i] * 100000000000) < 1) polycoefs[i] = 0; // rescale parameters for (i = 0; i <= order; i++) { polycoefs[i] = (1 / yscale) * polycoefs[i] * ldpow(xscale, i); coeffs.push_back(polycoefs[i]); } // create fg scaling function. interpolation based on coeffs which returns lookup table from 0 - 2^B-1. n-th order polinomial regression for (i = (int) xmin; i <= (int) xmax; i++) { double val = coeffs[0]; for (j = 1; j < coeffs.size(); j++) { val += (coeffs[j] * ldpow(i, j)); } val = Clip3(0.0, (double) (1 << bitDepth) - 1, val); scalingVec.push_back(val); } // save in scalingVec min and max value for further use scalingVec.push_back(xmax); scalingVec.push_back(xmin); return true; } // avg scaling vector with previous result to smooth transition betweeen frames void FGAnalyser::avg_scaling_vec(std::vector &scalingVec, ComponentID compID, int bitDepth) { int xmin = (int) scalingVec.back(); scalingVec.pop_back(); int xmax = (int) scalingVec.back(); scalingVec.pop_back(); static std::vector> scalingVecAvg(MAX_NUM_COMPONENT, std::vector((int)(1<=0 ; index--) if (scalingVecAvg[compID][index]) break; xmax = index; scalingVec.resize(xmax - xmin + 1); for (int i = xmin; i <= xmax; i++) scalingVec[i-xmin] = scalingVecAvg[compID][i]; scalingVec.push_back(xmax); scalingVec.push_back(xmin); } // Lloyd Max quantizer bool FGAnalyser::lloyd_max(std::vector &scalingVec, std::vector &quantizedVec, double &distortion, int numQuantizedLevels, int bitDepth) { if (scalingVec.size() <= 0) { throw("Empty training dataset."); } int xmin = (int) scalingVec.back(); scalingVec.pop_back(); scalingVec.pop_back(); // dummy pop_pack ==> int xmax = (int)scalingVec.back(); double ymin = 0.0; double ymax = 0.0; double init_training = 0.0; double tolerance = 0.0000001; double last_distor = 0.0; double rel_distor = 0.0; std::vector codebook(numQuantizedLevels); std::vector partition(numQuantizedLevels - 1); std::vector tmpVec(scalingVec.size(), 0.0); distortion = 0.0; ymin = scalingVec[0]; ymax = scalingVec[0]; for (int i = 0; i < scalingVec.size(); i++) { if (scalingVec[i] < ymin) ymin = scalingVec[i]; if (scalingVec[i] > ymax) ymax = scalingVec[i]; } init_training = (ymax - ymin) / numQuantizedLevels; if (init_training <= 0) { // msg(WARNING, "Invalid training dataset. Film grain parameter estimation is not performed. Default or previously estimated parameters are reused.\n"); return false; } // initial codebook double step = init_training / 2; for (int i = 0; i < numQuantizedLevels; i++) { codebook[i] = ymin + i * init_training + step; } // initial partition for (int i = 0; i < numQuantizedLevels - 1; i++) { partition[i] = (codebook[i] + codebook[i + 1]) / 2; } // quantizer initialization quantize(scalingVec, tmpVec, distortion, partition, codebook); double tolerance2 = std::numeric_limits::epsilon() * ymax; if (distortion > tolerance2) rel_distor = abs(distortion - last_distor) / distortion; else rel_distor = distortion; // optimization: find optimal codebook and partition while ((rel_distor > tolerance) && (rel_distor > tolerance2)) { for (int i = 0; i < numQuantizedLevels; i++) { int count = 0; double sum = 0.0; for (int j = 0; j < tmpVec.size(); j++) { if (codebook[i] == tmpVec[j]) { count++; sum += scalingVec[j]; } } if (count) { codebook[i] = sum / (double) count; } else { sum = 0.0; count = 0; if (i == 0) { for (int j = 0; j < tmpVec.size(); j++) { if (scalingVec[j] <= partition[i]) { count++; sum += scalingVec[j]; } } if (count) { codebook[i] = sum / (double) count; } else { codebook[i] = (partition[i] + ymin) / 2; } } else if (i == numQuantizedLevels - 1) { for (int j = 0; j < tmpVec.size(); j++) { if (scalingVec[j] >= partition[i - 1]) { count++; sum += scalingVec[j]; } } if (count) { codebook[i] = sum / (double) count; } else { codebook[i] = (partition[i - 1] + ymax) / 2; } } else { for (int j = 0; j < tmpVec.size(); j++) { if (scalingVec[j] >= partition[i - 1] && scalingVec[j] <= partition[i]) { count++; sum += scalingVec[j]; } } if (count) { codebook[i] = sum / (double) count; } else { codebook[i] = (partition[i - 1] + partition[i]) / 2; } } } } // compute and sort partition for (int i = 0; i < numQuantizedLevels - 1; i++) { partition[i] = (codebook[i] + codebook[i + 1]) / 2; } std::sort(partition.begin(), partition.end()); // final quantization - testing condition last_distor = distortion; quantize(scalingVec, tmpVec, distortion, partition, codebook); if (distortion > tolerance2) rel_distor = abs(distortion - last_distor) / distortion; else rel_distor = distortion; } // fill the final quantized vector quantizedVec.resize((int) (1 << bitDepth), 0); for (int i = 0; i < tmpVec.size(); i++) quantizedVec[i + xmin] = Clip3(0, FG_MAX_STANDARD_DEVIATION << (bitDepth - FG_BIT_DEPTH_8), (int) (tmpVec[i] + .5)); return true; } void FGAnalyser::quantize(std::vector &scalingVec, std::vector &quantizedVec, double &distortion, std::vector partition, std::vector codebook) { if (partition.size() <= 0 || codebook.size() <= 0) { throw("Check partitions and codebook."); } // reset previous quantizedVec to 0 and distortion to 0 std::fill(quantizedVec.begin(), quantizedVec.end(), 0.0); distortion = 0.0; // quantize input vector for (int i = 0; i < scalingVec.size(); i++) { for (int j = 0; j < partition.size(); j++) { quantizedVec[i] = quantizedVec[i] + (scalingVec[i] > partition[j]); // partition need to be sorted in acceding order } quantizedVec[i] = codebook[(int) quantizedVec[i]]; } // compute distortion - mse for (int i = 0; i < scalingVec.size(); i++) { distortion += ((scalingVec[i] - quantizedVec[i]) * (scalingVec[i] - quantizedVec[i])); } distortion /= scalingVec.size(); } // Set correctlly SEI parameters based on the quantized curve void FGAnalyser::setEstimatedParameters(std::vector &quantizedVec, unsigned int bitDepth, ComponentID compID) { std::vector> finalIntervalsandScalingFactors(3); // lower_bound, upper_bound, scaling_factor int cutoff_horizontal = m_compModel[compID].intensityValues[0].compModelValue[1]; int cutoff_vertical = m_compModel[compID].intensityValues[0].compModelValue[2]; // calculate intervals and scaling factors define_intervals_and_scalings(finalIntervalsandScalingFactors, quantizedVec, bitDepth); // merge small intervals with left or right interval for (int i = 0; i < finalIntervalsandScalingFactors[2].size(); i++) { int tmp1 = finalIntervalsandScalingFactors[1][i] - finalIntervalsandScalingFactors[0][i]; if (tmp1 < (2 << (bitDepth - FG_BIT_DEPTH_8))) { int diffRight = (i == (finalIntervalsandScalingFactors[2].size() - 1)) || (finalIntervalsandScalingFactors[2][i + 1] == 0) ? std::numeric_limits::max() : abs(finalIntervalsandScalingFactors[2][i] - finalIntervalsandScalingFactors[2][i + 1]); int diffLeft = (i == 0) || (finalIntervalsandScalingFactors[2][i - 1] == 0) ? std::numeric_limits::max() : abs(finalIntervalsandScalingFactors[2][i] - finalIntervalsandScalingFactors[2][i - 1]); if (diffLeft < diffRight) // merge with left { int tmp2 = finalIntervalsandScalingFactors[1][i - 1] - finalIntervalsandScalingFactors[0][i - 1]; int newScale = (tmp2 * finalIntervalsandScalingFactors[2][i - 1] + tmp1 * finalIntervalsandScalingFactors[2][i]) / (tmp2 + tmp1); finalIntervalsandScalingFactors[1][i - 1] = finalIntervalsandScalingFactors[1][i]; finalIntervalsandScalingFactors[2][i - 1] = newScale; for (int j = 0; j < 3; j++) finalIntervalsandScalingFactors[j].erase(finalIntervalsandScalingFactors[j].begin() + i); i--; } else // merge with right { int tmp2 = finalIntervalsandScalingFactors[1][i + 1] - finalIntervalsandScalingFactors[0][i + 1]; int newScale = (tmp2 * finalIntervalsandScalingFactors[2][i + 1] + tmp1 * finalIntervalsandScalingFactors[2][i]) / (tmp2 + tmp1); finalIntervalsandScalingFactors[1][i] = finalIntervalsandScalingFactors[1][i + 1]; finalIntervalsandScalingFactors[2][i] = newScale; for (int j = 0; j < 3; j++) finalIntervalsandScalingFactors[j].erase(finalIntervalsandScalingFactors[j].begin() + i + 1); i--; } } } // scale to 8-bit range as supported by current sei and rdd5 scale_down(finalIntervalsandScalingFactors, bitDepth); // because of scaling in previous step, some intervals may overlap. Check intervals for errors. confirm_intervals(finalIntervalsandScalingFactors); // set number of intervals; exculde intervals with scaling factor 0. m_compModel[compID].numIntensityIntervals = (int) finalIntervalsandScalingFactors[2].size() - (int) count(finalIntervalsandScalingFactors[2].begin(), finalIntervalsandScalingFactors[2].end(), 0); if (m_compModel[compID].numIntensityIntervals == 0) { // check if all intervals are 0, and if yes set presentFlag to false m_compModel[compID].bPresentFlag = false; return; } // set final interval boundaries and scaling factors. check if some interval has scaling factor 0, and do not encode // them within SEI. for (int i = 0, j = 0; i < finalIntervalsandScalingFactors[2].size(); i++) { if (finalIntervalsandScalingFactors[2][i] != 0) { m_compModel[compID].intensityValues[j].intensityIntervalLowerBound = finalIntervalsandScalingFactors[0][i]; m_compModel[compID].intensityValues[j].intensityIntervalUpperBound = finalIntervalsandScalingFactors[1][i]; m_compModel[compID].intensityValues[j].compModelValue[0] = finalIntervalsandScalingFactors[2][i]; m_compModel[compID].intensityValues[j].compModelValue[1] = cutoff_horizontal; m_compModel[compID].intensityValues[j].compModelValue[2] = cutoff_vertical; j++; } } } long double FGAnalyser::ldpow(long double n, unsigned p) { long double x = 1; unsigned i; for (i = 0; i < p; i++) x = x * n; return x; } // find bounds of intensity intervals and scaling factors for each interval void FGAnalyser::define_intervals_and_scalings(std::vector> ¶meters, std::vector &quantizedVec, int bitDepth) { parameters[0].push_back(0); parameters[2].push_back(quantizedVec[0]); for (int i = 0; i < quantizedVec.size() - 1; i++) { if (quantizedVec[i] != quantizedVec[i + 1]) { parameters[0].push_back(i + 1); parameters[1].push_back(i); parameters[2].push_back(quantizedVec[i + 1]); } } parameters[1].push_back((1 << bitDepth) - 1); } // scale everything to 8-bit ranges as supported by SEI message void FGAnalyser::scale_down(std::vector> ¶meters, int bitDepth) { for (int i = 0; i < parameters[2].size(); i++) { parameters[0][i] >>= (bitDepth - FG_BIT_DEPTH_8); parameters[1][i] >>= (bitDepth - FG_BIT_DEPTH_8); parameters[2][i] <<= m_log2ScaleFactor; parameters[2][i] >>= (bitDepth - FG_BIT_DEPTH_8); } } // check if intervals are properly set after scaling to 8-bit representation void FGAnalyser::confirm_intervals(std::vector> ¶meters) { std::vector tmp; for (int i = 0; i < parameters[2].size(); i++) { tmp.push_back(parameters[0][i]); tmp.push_back(parameters[1][i]); } for (int i = 0; i < tmp.size() - 1; i++) { if (tmp[i] == tmp[i + 1]) tmp[i + 1]++; } for (int i = 0; i < parameters[2].size(); i++) { parameters[0][i] = tmp[2 * i]; parameters[1][i] = tmp[2 * i + 1]; } } void FGAnalyser::extend_points(std::vector &data_x, std::vector &data_y, int bitDepth) { int xmin = data_x[0]; int xmax = data_x[0]; int ymin = data_y[0]; int ymax = data_y[0]; for (int i = 0; i < data_x.size(); i++) { if (data_x[i] < xmin) { xmin = data_x[i]; ymin = data_y[i]; // not real ymin } if (data_x[i] > xmax) { xmax = data_x[i]; ymax = data_y[i]; // not real ymax } } // extend points to the left int step = POINT_STEP; double scale = POINT_SCALE; int num_extra_point_left = MAX_NUM_POINT_TO_EXTEND; int num_extra_point_right = MAX_NUM_POINT_TO_EXTEND; while (xmin >= step && ymin > 1 && num_extra_point_left > 0) { xmin -= step; ymin = static_cast(ymin / scale); data_x.push_back(xmin); data_y.push_back(ymin); num_extra_point_left--; } // extend points to the right while (xmax + step <= ((1 << bitDepth) - 1) && ymax > 1 && num_extra_point_right > 0) { xmax += step; ymax = static_cast(ymax / scale); data_x.push_back(xmax); data_y.push_back(ymax); num_extra_point_right--; } for (int i = 0; i < data_x.size(); i++) { if (data_x[i] < MIN_INTENSITY || data_x[i] > MAX_INTENSITY) { data_x.erase(data_x.begin() + i); data_y.erase(data_y.begin() + i); i--; } } } void FGAnalyser::subtract(TComPicYuv& buffer1, TComPicYuv& buffer2) { for (int compIdx = 0; compIdx < getNumberValidComponents(buffer1.getChromaFormat()); compIdx++) { ComponentID compID = ComponentID(compIdx); const Int widthSrc = buffer1.getWidth(compID); const Int heightSrc = buffer1.getHeight(compID); for (int x=0; x #include #include #if JVET_X0048_X0103_FILM_GRAIN static const double PI = 3.14159265358979323846; static const int MAXPAIRS = 256; static const int MAXORDER = 8; // maximum order of polinomial fitting static const int MAX_REAL_SCALE = 16; static const int ORDER = 4; // order of polinomial function static const int QUANT_LEVELS = 4; // number of quantization levels in lloyd max quantization static const int INTERVAL_SIZE = 16; static const int MIN_ELEMENT_NUMBER_PER_INTENSITY_INTERVAL = 8; static const int MIN_POINTS_FOR_INTENSITY_ESTIMATION = 40; // 5*8 = 40; 5 intervals with at least 8 points static const int MIN_BLOCKS_FOR_CUTOFF_ESTIMATION = 2; // 2 blocks of 64 x 64 size static const int POINT_STEP = 16; // step size in point extension static const int MAX_NUM_POINT_TO_EXTEND = 4; // max point in extension static const double POINT_SCALE = 1.25; // scaling in point extension static const double VAR_SCALE_DOWN = 1.2; // filter out large points static const double VAR_SCALE_UP = 0.6; // filter out large points static const int NUM_PASSES = 2; // number of passes when fitting the function static const int NBRS = 1; // minimum number of surrounding points in order to keep it for further analysis (within the widnow range) static const int WINDOW = 1; // window to check surrounding points static const int MIN_INTENSITY = 40; static const int MAX_INTENSITY = 950; //! \ingroup SEIFilmGrainAnalyzer //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== struct Picture; typedef std::vector> PelMatrix; typedef std::vector> PelMatrixDouble; typedef std::vector> PelMatrixLongDouble; typedef std::vector PelVectorLongDouble; class Canny { public: Canny(); ~Canny(); unsigned int m_convWidthG = 5, m_convHeightG = 5; // Pixel's row and col positions for Gauss filtering void detect_edges(const TComPicYuv* orig, TComPicYuv* dest, unsigned int uiBitDepth, ComponentID compID); private: static const int m_gx[3][3]; // Sobel kernel x static const int m_gy[3][3]; // Sobel kernel y static const int m_gauss5x5[5][5]; // Gauss 5x5 kernel, integer approximation unsigned int m_convWidthS = 3, m_convHeightS = 3; // Pixel's row and col positions for Sobel filtering double m_lowThresholdRatio = 0.1; // low threshold rato int m_highThresholdRatio = 3; // high threshold rato void gradient (TComPicYuv* buff1, TComPicYuv* buff2, unsigned int width, unsigned int height, unsigned int convWidthS, unsigned int convHeightS, unsigned int bitDepth, ComponentID compID ); void suppressNonMax (TComPicYuv* buff1, TComPicYuv* buff2, unsigned int width, unsigned int height, ComponentID compID ); void doubleThreshold(TComPicYuv* buff, unsigned int width, unsigned int height, /*unsigned int windowSizeRatio,*/ unsigned int bitDepth, ComponentID compID); void edgeTracking (TComPicYuv* buff1, unsigned int width, unsigned int height, unsigned int windowWidth, unsigned int windowHeight, unsigned int bitDepth, ComponentID compID ); }; class Morph { public: Morph(); ~Morph(); int dilation (TComPicYuv* buff, unsigned int bitDepth, ComponentID compID, int numIter, int iter = 0); int erosion (TComPicYuv* buff, unsigned int bitDepth, ComponentID compID, int numIter, int iter = 0); private: unsigned int m_kernelSize = 3; // Dilation and erosion kernel size }; class FGAnalyser { public: FGAnalyser(); ~FGAnalyser(); void init(const int width, const int height, const int sourcePaddingWidth, const int sourcePaddingHeight, const InputColourSpaceConversion ipCSC, const bool bClipInputVideoToRec709Range, const ChromaFormat inputChroma, const BitDepths& inputBitDepths, const BitDepths& outputBitDepths, const int frameSkip, const bool doAnalysis[], std::string filmGrainExternalMask, std::string filmGrainExternalDenoised); void destroy (); bool initBufs (TComPic* pic); void estimate_grain (TComPic* pic); int getLog2scaleFactor() { return m_log2ScaleFactor; }; SEIFilmGrainCharacteristics::CompModel getCompModel(int idx) { return m_compModel[idx]; }; private: std::string m_filmGrainExternalMask = ""; std::string m_filmGrainExternalDenoised = ""; int m_sourcePadding[2]; InputColourSpaceConversion m_ipCSC; bool m_bClipInputVideoToRec709Range; BitDepths m_bitDepthsIn; int m_frameSkip; ChromaFormat m_chromaFormatIDC; BitDepths m_bitDepths; bool m_doAnalysis[MAX_NUM_COMPONENT] = { false, false, false }; Canny m_edgeDetector; Morph m_morphOperation; double m_lowIntensityRatio = 0.1; // supress everything below 0.1*maxIntensityOffset static constexpr double m_tap_filtar[3] = { 1, 2, 1 }; static constexpr double m_normTap = 4.0; // fg model parameters int m_log2ScaleFactor; SEIFilmGrainCharacteristics::CompModel m_compModel[MAX_NUM_COMPONENT]; TComPicYuv *m_originalBuf = nullptr; TComPicYuv *m_workingBuf = nullptr; TComPicYuv *m_maskBuf = nullptr; void findMask (); void estimate_grain_parameters (); void block_transform (const TComPicYuv& buff1, std::vector& squared_dct_grain_block_list, int offsetX, int offsetY, unsigned int bitDepth, ComponentID compID); void estimate_cutoff_freq (const std::vector& blocks, ComponentID compID); int cutoff_frequency (std::vector& mean); void estimate_scaling_factors (std::vector& data_x, std::vector& data_y, unsigned int bitDepth, ComponentID compID); bool fit_function (std::vector& data_x, std::vector& data_y, std::vector& coeffs, std::vector& scalingVec, int order, int bitDepth, bool second_pass); void avg_scaling_vec (std::vector &scalingVec, ComponentID compID, int bitDepth); bool lloyd_max (std::vector& scalingVec, std::vector& quantizedVec, double& distortion, int numQuantizedLevels, int bitDepth); void quantize (std::vector& scalingVec, std::vector& quantizedVec, double& distortion, std::vector partition, std::vector codebook); void extend_points (std::vector& data_x, std::vector& data_y, int bitDepth); void setEstimatedParameters (std::vector& quantizedVec, unsigned int bitDepth, ComponentID compID); void define_intervals_and_scalings(std::vector>& parameters, std::vector& quantizedVec, int bitDepth); void scale_down (std::vector>& parameters, int bitDepth); void confirm_intervals (std::vector>& parameters); long double ldpow (long double n, unsigned p); int meanVar (TComPicYuv& buffer, int windowSize, ComponentID compID, int offsetX, int offsetY, bool getVar); int count_edges (TComPicYuv& buffer, int windowSize, ComponentID compID, int offsetX, int offsetY); void subsample (const TComPicYuv& input, TComPicYuv& output, ComponentID compID, const int factor = 2, const int padding = 0) const; void upsample (const TComPicYuv& input, TComPicYuv& output, ComponentID compID, const int factor = 2, const int padding = 0) const; void combineMasks (TComPicYuv& buff, TComPicYuv& buff2, ComponentID compID); void suppressLowIntensity (const TComPicYuv& buff1, TComPicYuv& buff2, unsigned int bitDepth, ComponentID compID); void subtract (TComPicYuv& buffer1, TComPicYuv& buffer2); }; // END CLASS DEFINITION //! \} #endif #endif // __SEIFILMGRAINANALYZER__ HM-HM-18.0/source/Lib/TLibCommon/SEIFilmGrainSynthesizer.cpp000066400000000000000000001473711442026013100234540ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainSynthesizer.cpp \brief SMPTE RDD5 based film grain synthesis functionality from SEI messages */ #include "SEIFilmGrainSynthesizer.h" #include #include #if JVET_X0048_X0103_FILM_GRAIN /* static look up table definitions */ static const int8_t gaussianLUT[2048] = { -11, 12, 103, -11, 42, -35, 12, 59, 77, 98, -87, 3, 65, -78, 45, 56, -51, 21, 13, -11, -20, -19, 33, -127, 17, -6, -105, 18, 19, 71, 48, -10, -38, 42, -2, 75, -67, 52, -90, 33, -47, 21, -3, -56, 49, 1, -57, -42, -1, 120, -127, -108, -49, 9, 14, 127, 122, 109, 52, 127, 2, 7, 114, 19, 30, 12, 77, 112, 82, -61, -127, 111, -52, -29, 2, -49, -24, 58, -29, -73, 12, 112, 67, 79, -3, -114, -87, -6, -5, 40, 58, -81, 49, -27, -31, -34, -105, 50, 16, -24, -35, -14, -15, -127, -55, -22, -55, -127, -112, 5, -26, -72, 127, 127, -2, 41, 87, -65, -16, 55, 19, 91, -81, -65, -64, 35, -7, -54, 99, -7, 88, 125, -26, 91, 0, 63, 60, -14, -23, 113, -33, 116, 14, 26, 51, -16, 107, -8, 53, 38, -34, 17, -7, 4, -91, 6, 63, 63, -15, 39, -36, 19, 55, 17, -51, 40, 33, -37, 126, -39, -118, 17, -30, 0, 19, 98, 60, 101, -12, -73, -17, -52, 98, 3, 3, 60, 33, -3, -2, 10, -42, -106, -38, 14, 127, 16, -127, -31, -86, -39, -56, 46, -41, 75, 23, -19, -22, -70, 74, -54, -2, 32, -45, 17, -92, 59, -64, -67, 56, -102, -29, -87, -34, -92, 68, 5, -74, -61, 93, -43, 14, -26, -38, -126, -17, 16, -127, 64, 34, 31, 93, 17, -51, -59, 71, 77, 81, 127, 127, 61, 33, -106, -93, 0, 0, 75, -69, 71, 127, -19, -111, 30, 23, 15, 2, 39, 92, 5, 42, 2, -6, 38, 15, 114, -30, -37, 50, 44, 106, 27, 119, 7, -80, 25, -68, -21, 92, -11, -1, 18, 41, -50, 79, -127, -43, 127, 18, 11, -21, 32, -52, 27, -88, -90, -39, -19, -10, 24, -118, 72, -24, -44, 2, 12, 86, -107, 39, -33, -127, 47, 51, -24, -22, 46, 0, 15, -35, -69, -2, -74, 24, -6, 0, 29, -3, 45, 32, -32, 117, -45, 79, -24, -17, -109, -10, -70, 88, -48, 24, -91, 120, -37, 50, -127, 58, 32, -82, -10, -17, -7, 46, -127, -15, 89, 127, 17, 98, -39, -33, 37, 42, -40, -32, -21, 105, -19, 19, 19, -59, -9, 30, 0, -127, 34, 127, -84, 75, 24, -40, -49, -127, -107, -14, 45, -75, 1, 30, -20, 41, -68, -40, 12, 127, -3, 5, 20, -73, -59, -127, -3, -3, -53, -6, -119, 93, 120, -80, -50, 0, 20, -46, 67, 78, -12, -22, -127, 36, -41, 56, 119, -5, -116, -22, 68, -14, -90, 24, -82, -44, -127, 107, -25, -37, 40, -7, -7, -82, 5, -87, 44, -34, 9, -127, 39, 70, 49, -63, 74, -49, 109, -27, -89, -47, -39, 44, 49, -4, 60, -42, 80, 9, -127, -9, -56, -49, 125, -66, 47, 36, 117, 15, -11, -96, 109, 94, -17, -56, 70, 8, -14, -5, 50, 37, -45, 120, -30, -76, 40, -46, 6, 3, 69, 17, -78, 1, -79, 6, 127, 43, 26, 127, -127, 28, -55, -26, 55, 112, 48, 107, -1, -77, -1, 53, -9, -22, -43, 123, 108, 127, 102, 68, 46, 5, 1, 123, -13, -55, -34, -49, 89, 65, -105, -5, 94, -53, 62, 45, 30, 46, 18, -35, 15, 41, 47, -98, -24, 94, -75, 127, -114, 127, -68, 1, -17, 51, -95, 47, 12, 34, -45, -75, 89, -107, -9, -58, -29, -109, -24, 127, -61, -13, 77, -45, 17, 19, 83, -24, 9, 127, -66, 54, 4, 26, 13, 111, 43, -113, -22, 10, -24, 83, 67, -14, 75, -123, 59, 127, -12, 99, -19, 64, -38, 54, 9, 7, 61, -56, 3, -57, 113, -104, -59, 3, -9, -47, 74, 85, -55, -34, 12, 118, 28, 93, -72, 13, -99, -72, -20, 30, 72, -94, 19, -54, 64, -12, -63, -25, 65, 72, -10, 127, 0, -127, 103, -20, -73, -112, -103, -6, 28, -42, -21, -59, -29, -26, 19, -4, -51, 94, -58, -95, -37, 35, 20, -69, 127, -19, -127, -22, -120, -53, 37, 74, -127, -1, -12, -119, -53, -28, 38, 69, 17, 16, -114, 89, 62, 24, 37, -23, 49, -101, -32, -9, -95, -53, 5, 93, -23, -49, -8, 51, 3, -75, -90, -10, -39, 127, -86, -22, 20, 20, 113, 75, 52, -31, 92, -63, 7, -12, 46, 36, 101, -43, -17, -53, -7, -38, -76, -31, -21, 62, 31, 62, 20, -127, 31, 64, 36, 102, -85, -10, 77, 80, 58, -79, -8, 35, 8, 80, -24, -9, 3, -17, 72, 127, 83, -87, 55, 18, -119, -123, 36, 10, 127, 56, -55, 113, 13, 26, 32, -13, -48, 22, -13, 5, 58, 27, 24, 26, -11, -36, 37, -92, 78, 81, 9, 51, 14, 67, -13, 0, 32, 45, -76, 32, -39, -22, -49, -127, -27, 31, -9, 36, 14, 71, 13, 57, 12, -53, -86, 53, -44, -35, 2, 127, 12, -66, -44, 46, -115, 3, 10, 56, -35, 119, -19, -61, 52, -59, -127, -49, -23, 4, -5, 17, -82, -6, 127, 25, 79, 67, 64, -25, 14, -64, -37, -127, -28, 21, -63, 66, -53, -41, 109, -62, 15, -22, 13, 29, -63, 20, 27, 95, -44, -59, -116, -10, 79, -49, 22, -43, -16, 46, -47, -120, -36, -29, -52, -44, 29, 127, -13, 49, -9, -127, 75, -28, -23, 88, 59, 11, -95, 81, -59, 58, 60, -26, 40, -92, -3, -22, -58, -45, -59, -22, -53, 71, -29, 66, -32, -23, 14, -17, -66, -24, -28, -62, 47, 38, 17, 16, -37, -24, -11, 8, -27, -19, 59, 45, -49, -47, -4, -22, -81, 30, -67, -127, 74, 102, 5, -18, 98, 34, -66, 42, -52, 7, -59, 24, -58, -19, -24, -118, -73, 91, 15, -16, 79, -32, -79, -127, -36, 41, 77, -83, 2, 56, 22, -75, 127, -16, -21, 12, 31, 56, -113, -127, 90, 55, 61, 12, 55, -14, -113, -14, 32, 49, -67, -17, 91, -10, 1, 21, 69, -70, 99, -19, -112, 66, -90, -10, -9, -71, 127, 50, -81, -49, 24, 61, -61, -111, 7, -41, 127, 88, -66, 108, -127, -6, 36, -14, 41, -50, 14, 14, 73, -101, -28, 77, 127, -8, -100, 88, 38, 121, 88, -125, -60, 13, -94, -115, 20, -67, -87, -94, -119, 44, -28, -30, 18, 5, -53, -61, 20, -43, 11, -77, -60, 13, 29, 3, 6, -72, 38, -60, -11, 108, -53, 41, 66, -12, -127, -127, -49, 24, 29, 46, 36, 91, 34, -33, 116, -51, -34, -52, 91, 7, -83, 73, -26, -103, 24, -10, 76, 84, 5, 68, -80, -13, -17, -32, -48, 20, 50, 26, 10, 63, -104, -14, 37, 127, 114, 97, 35, 1, -33, -55, 127, -124, -33, 61, -7, 119, -32, -127, -53, -42, 63, 3, -5, -26, 70, -58, -33, -44, -43, 34, -56, -127, 127, 25, -35, -11, 16, -81, 29, -58, 40, -127, -127, 20, -47, -11, -36, -63, -52, -32, -82, 78, -76, -73, 8, 27, -72, -9, -74, -85, -86, -57, 25, 78, -10, -97, 35, -65, 8, -59, 14, 1, -42, 32, -88, -44, 17, -3, -9, 59, 40, 12, -108, -40, 24, 34, 18, -28, 2, 51, -110, -4, 100, 1, 65, 22, 0, 127, 61, 45, 25, -31, 6, 9, -7, -48, 99, 16, 44, -2, -40, 32, -39, -52, 10, -110, -19, 56, -127, 69, 26, 51, 92, 40, 61, -52, 45, -38, 13, 85, 122, 27, 66, 45, -111, -83, -3, 31, 37, 19, -36, 58, 71, 39, -78, -47, 58, -78, 8, -62, -36, -14, 61, 42, -127, 71, -4, 24, -54, 52, -127, 67, -4, -42, 30, -63, 59, -3, -1, -18, -46, -92, -81, -96, -14, -53, -10, -11, -77, 13, 1, 8, -67, -127, 127, -28, 26, -14, 18, -13, -26, 2, 10, -46, -32, -15, 27, -31, -59, 59, 77, -121, 28, 40, -54, -62, -31, -21, -37, -32, -6, -127, -25, -60, 70, -127, 112, -127, 127, 88, -7, 116, 110, 53, 87, -127, 3, 16, 23, 74, -106, -51, 3, 74, -82, -112, -74, 65, 81, 25, 53, 127, -45, -50, -103, -41, -65, -29, 79, -67, 64, -33, -30, -8, 127, 0, -13, -51, 67, -14, 5, -92, 29, -35, -8, -90, -57, -3, 36, 43, 44, -31, -69, -7, 36, 39, -51, 43, -81, 58, 6, 127, 12, 57, 66, 46, 59, -43, -42, 41, -15, -120, 24, 3, -11, 19, -13, 51, 28, 3, 55, -48, -12, -1, 2, 97, -19, 29, 42, 13, 43, 78, -44, 56, -108, -43, -19, 127, 15, -11, -18, -81, 83, -37, 77, -109, 15, 65, -50, 43, 12, 13, 27, 28, 61, 57, 30, 26, 106, -18, 56, 13, 97, 4, -8, -62, -103, 94, 108, -44, 52, 27, -47, -9, 105, -53, 46, 89, 103, -33, 38, -34, 55, 51, 70, -94, -35, -87, -107, -19, -31, 9, -19, 79, -14, 77, 5, -19, -107, 85, 21, -45, -39, -42, 9, -29, 74, 47, -75, 60, -127, 120, -112, -57, -32, 41, 7, 79, 76, 66, 57, 41, -25, 31, 37, -47, -36, 43, -73, -37, 63, 127, -69, -52, 90, -33, -61, 60, -55, 44, 15, 4, -67, 13, -92, 64, 29, -39, -3, 83, -2, -38, -85, -86, 58, 35, -69, -61, 29, -37, -95, -78, 4, 30, -4, -32, -80, -22, -9, -77, 46, 7, -93, -71, 65, 9, -50, 127, -70, 26, -12, -39, -114, 63, -127, -100, 4, -32, 111, 22, -60, 65, -101, 26, -42, 21, -59, -27, -74, 2, -94, 6, 126, 5, 76, -88, -9, -43, -101, 127, 1, 125, 92, -63, 52, 56, 4, 81, -127, 127, 80, 127, -29, 30, 116, -74, -17, -57, 105, 48, 45, 25, -72, 48, -38, -108, 31, -34, 4, -11, 41, -127, 52, -104, -43, -37, 52, 2, 47, 87, -9, 77, 27, -41, -25, 90, 86, -56, 75, 10, 33, 78, 58, 127, 127, -7, -73, 49, -33, -106, -35, 38, 57, 53, -17, -4, 83, 52, -108, 54, -125, 28, 23, 56, -43, -88, -17, -6, 47, 23, -9, 0, -13, 111, 75, 27, -52, -38, -34, 39, 30, 66, 39, 38, -64, 38, 3, 21, -32, -51, -28, 54, -38, -87, 20, 52, 115, 18, -81, -70, 0, -14, -46, -46, -3, 125, 16, -14, 23, -82, -84, -69, -20, -65, -127, 9, 81, -49, 61, 7, -36, -45, -42, 57, -26, 47, 20, -85, 46, -13, 41, -37, -75, -60, 86, -78, -127, 12, 50, 2, -3, 13, 47, 5, 19, -78, -55, -27, 65, -71, 12, -108, 20, -16, 11, -31, 63, -55, 37, 75, -17, 127, -73, -33, -28, -120, 105, 68, 106, -103, -106, 71, 61, 2, 23, -3, 33, -5, -15, -67, -15, -23, -54, 15, -63, 76, 58, -110, 1, 83, -27, 22, 75, -39, -17, -11, 64, -17, -127, -54, -66, 31, 96, 116, 3, -114, -7, -108, -63, 97, 9, 50, 8, 75, -28, 72, 112, -36, -112, 95, -50, 23, -13, -19, 55, 21, 23, 92, 91, 22, -49, 16, -75, 23, 9, -49, -97, -37, 49, -36, 36, -127, -86, 43, 127, -24, -24, 84, 83, -35, -34, -12, 109, 102, -38, 51, -68, 34, 19, -22, 49, -32, 127, 40, 24, -93, -4, -3, 105, 3, -58, -18, 8, 127, -18, 125, 68, 69, -62, 30, -36, 54, -57, -24, 17, 43, -36, -27, -57, -67, -21, -10, -49, 68, 12, 65, 4, 48, 55, 127, -75, 44, 89, -66, -13, -78, -82, -91, 22, 30, 33, -40, -87, -34, 96, -91, 39, 10, -64, -3, -12, 127, -50, -37, -56, 23, -35, -36, -54, 90, -91, 2, 50, 77, -6, -127, 16, 46, -5, -73, 0, -56, -18, -72, 28, 93, 60, 49, 20, 18, 111, -111, 32, -83, 47, 47, -10, 35, -88, 43, 57, -98, 127, -17, 0, 1, -39, -127, -2, 0, 63, 93, 0, 36, -66, -61, -19, 39, -127, 58, 50, -17, 127, 88, -43, -108, -51, -16, 7, -36, 68, 46, -14, 107, 40, 57, 7, 19, 8, 3, 88, -90, -92, -18, -21, -24, 13, 7, -4, -78, -91, -4, 8, -35, -5, 19, 2, -111, 4, -66, -81, 122, -20, -34, -37, -84, 127, 68, 46, 17, 47 }; static const uint32_t seedLUT[256] = { 747538460, 1088979410, 1744950180, 1767011913, 1403382928, 521866116, 1060417601, 2110622736, 1557184770, 105289385, 585624216, 1827676546, 1191843873, 1018104344, 1123590530, 663361569, 2023850500, 76561770, 1226763489, 80325252, 1992581442, 502705249, 740409860, 516219202, 557974537, 1883843076, 720112066, 1640137737, 1820967556, 40667586, 155354121, 1820967557, 1115949072, 1631803309, 98284748, 287433856, 2119719977, 988742797, 1827432592, 579378475, 1017745956, 1309377032, 1316535465, 2074315269, 1923385360, 209722667, 1546228260, 168102420, 135274561, 355958469, 248291472, 2127839491, 146920100, 585982612, 1611702337, 696506029, 1386498192, 1258072451, 1212240548, 1043171860, 1217404993, 1090770605, 1386498193, 169093201, 541098240, 1468005469, 456510673, 1578687785, 1838217424, 2010752065, 2089828354, 1362717428, 970073673, 854129835, 714793201, 1266069081, 1047060864, 1991471829, 1098097741, 913883585, 1669598224, 1337918685, 1219264706, 1799741108, 1834116681, 683417731, 1120274457, 1073098457, 1648396544, 176642749, 31171789, 718317889, 1266977808, 1400892508, 549749008, 1808010512, 67112961, 1005669825, 903663673, 1771104465, 1277749632, 1229754427, 950632997, 1979371465, 2074373264, 305357524, 1049387408, 1171033360, 1686114305, 2147468765, 1941195985, 117709841, 809550080, 991480851, 1816248997, 1561503561, 329575568, 780651196, 1659144592, 1910793616, 604016641, 1665084765, 1530186961, 1870928913, 809550081, 2079346113, 71307521, 876663040, 1073807360, 832356664, 1573927377, 204073344, 2026918147, 1702476788, 2043881033, 57949587, 2001393952, 1197426649, 1186508931, 332056865, 950043140, 890043474, 349099312, 148914948, 236204097, 2022643605, 1441981517, 498130129, 1443421481, 924216797, 1817491777, 1913146664, 1411989632, 929068432, 495735097, 1684636033, 1284520017, 432816184, 1344884865, 210843729, 676364544, 234449232, 12112337, 1350619139, 1753272996, 2037118872, 1408560528, 533334916, 1043640385, 357326099, 201376421, 110375493, 541106497, 416159637, 242512193, 777294080, 1614872576, 1535546636, 870600145, 910810409, 1821440209, 1605432464, 1145147393, 951695441, 1758494976, 1506656568, 1557150160, 608221521, 1073840384, 217672017, 684818688, 1750138880, 16777217, 677990609, 953274371, 1770050213, 1359128393, 1797602707, 1984616737, 1865815816, 2120835200, 2051677060, 1772234061, 1579794881, 1652821009, 1742099468, 1887260865, 46468113, 1011925248, 1134107920, 881643832, 1354774993, 472508800, 1892499769, 1752793472, 1962502272, 687898625, 883538000, 1354355153, 1761673473, 944820481, 2020102353, 22020353, 961597696, 1342242816, 964808962, 1355809701, 17016649, 1386540177, 647682692, 1849012289, 751668241, 1557184768, 127374604, 1927564752, 1045744913, 1614921984, 43588881, 1016185088, 1544617984, 1090519041, 136122424, 215038417, 1563027841, 2026918145, 1688778833, 701530369, 1372639488, 1342242817, 2036945104, 953274369, 1750192384, 16842753, 964808960, 1359020032, 1358954497 }; static const uint32_t deblockFactor[13] = { 64, 71, 77, 84, 90, 96, 103, 109, 116, 122, 128, 128, 128 }; SEIFilmGrainSynthesizer::SEIFilmGrainSynthesizer() : m_width (0) , m_height (0) , m_chromaFormat (NUM_CHROMA_FORMAT) , m_bitDepth (0) , m_idrPicId (0) , m_grainSynt (NULL) , m_fgsBlkSize (8) , m_poc (0) , m_errorCode (0) , m_fgcParameters (NULL) { } void SEIFilmGrainSynthesizer::create(uint32_t width, uint32_t height, ChromaFormat fmt, uint8_t bitDepth, uint32_t idrPicId) { m_width = width; m_height = height; m_chromaFormat = fmt; m_bitDepth = bitDepth; m_idrPicId = idrPicId; m_fgsBlkSize = 8; m_errorCode = 0; if (!m_grainSynt) m_grainSynt = new GrainSynthesisStruct; if (!m_fgcParameters) m_fgcParameters = new SEIFilmGrainCharacteristics; } SEIFilmGrainSynthesizer::~SEIFilmGrainSynthesizer() { destroy(); } void SEIFilmGrainSynthesizer::fgsInit() { deriveFGSBlkSize(); dataBaseGen(); } void SEIFilmGrainSynthesizer::destroy() { if (m_fgcParameters) { delete m_fgcParameters; m_fgcParameters = NULL; } if (m_grainSynt) { delete m_grainSynt; m_grainSynt = NULL; } } void SEIFilmGrainSynthesizer::grainSynthesizeAndBlend(TComPicYuv* pGrainBuf, Bool isIdrPic) { uint8_t numComp = MAX_NUM_COMPONENT, compCtr; /* number of color components */ uint8_t color_offset[MAX_NUM_COMPONENT]; uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT], strideComp[MAX_NUM_COMPONENT]; uint32_t * offsetsArr[MAX_NUM_COMPONENT]; Pel * decComp[MAX_NUM_COMPONENT]; uint32_t pseudoRandValEc; uint32_t picOffset; /* from SMPTE RDD5 */ color_offset[0] = COLOUR_OFFSET_LUMA; color_offset[1] = COLOUR_OFFSET_CR; color_offset[2] = COLOUR_OFFSET_CB; if (0 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag) { return; } widthComp[0] = m_width; heightComp[0] = m_height; if (CHROMA_420 == m_chromaFormat) { widthComp[1] = (m_width >> 1); widthComp[2] = (m_width >> 1); heightComp[1] = (m_height >> 1); heightComp[2] = (m_height >> 1); } else if (CHROMA_422 == m_chromaFormat) { widthComp[1] = (m_width >> 1); widthComp[2] = (m_width >> 1); heightComp[1] = m_height; heightComp[2] = m_height; } else if (CHROMA_400 == m_chromaFormat) { numComp = 1; } /*Allocate memory for offsets assuming 16x16 block size, 32x32 will need lesser than this*/ uint32_t maxNumBlocks = ((m_width >> 4) + 1) * ((m_height >> 4) + 1); for (compCtr = 0; compCtr < numComp; compCtr++) { offsetsArr[compCtr] = new uint32_t[maxNumBlocks]; } decComp[0] = pGrainBuf->getAddr(COMPONENT_Y); decComp[1] = pGrainBuf->getAddr(COMPONENT_Cb); decComp[2] = pGrainBuf->getAddr(COMPONENT_Cr); /* component strides */ strideComp[0] = pGrainBuf->getStride(COMPONENT_Y); strideComp[1] = 0; strideComp[2] = 0; if (CHROMA_400 != m_chromaFormat) { strideComp[1] = pGrainBuf->getStride(COMPONENT_Cb); strideComp[2] = pGrainBuf->getStride(COMPONENT_Cr); } int32_t numBlks_x[MAX_NUM_COMPONENT]; int32_t numBlks_y[MAX_NUM_COMPONENT]; picOffset = m_poc; for (compCtr = 0; compCtr < numComp; compCtr++) { if (FG_BLK_32 == m_fgsBlkSize) { numBlks_x[compCtr] = (widthComp[compCtr] >> 5) + ((widthComp[compCtr] & 0x1F) ? 1 : 0); numBlks_y[compCtr] = (heightComp[compCtr] >> 5) + ((heightComp[compCtr] & 0x1F) ? 1 : 0); } else { numBlks_x[compCtr] = (widthComp[compCtr] >> 4) + ((widthComp[compCtr] & 0xF) ? 1 : 0); numBlks_y[compCtr] = (heightComp[compCtr] >> 4) + ((heightComp[compCtr] & 0xF) ? 1 : 0); } } for (compCtr = 0; compCtr < numComp; compCtr++) { if (1 == m_fgcParameters->m_compModel[compCtr].bPresentFlag) { uint32_t *tmp = offsetsArr[compCtr]; int i, j; /* Seed initialization for current picture*/ pseudoRandValEc = seedLUT[((picOffset + color_offset[compCtr]) & 0xFF)]; for (i = 0; i < numBlks_y[compCtr]; i++) { for (j = 0; j < numBlks_x[compCtr]; j++) { *tmp = pseudoRandValEc; pseudoRandValEc = prng(pseudoRandValEc); tmp++; } } } } m_fgsArgs.numComp = numComp; for (compCtr = 0; compCtr < numComp; compCtr++) { if (1 == m_fgcParameters->m_compModel[compCtr].bPresentFlag) { m_fgsArgs.decComp[compCtr] = decComp[compCtr]; m_fgsArgs.widthComp[compCtr] = widthComp[compCtr]; m_fgsArgs.strideComp[compCtr] = strideComp[compCtr]; m_fgsArgs.fgsOffsets[compCtr] = offsetsArr[compCtr]; if (FG_BLK_32 == m_fgsBlkSize) { m_fgsArgs.heightComp[compCtr] = numBlks_y[compCtr] * FG_BLK_32; } else { m_fgsArgs.heightComp[compCtr] = numBlks_y[compCtr] * FG_BLK_16; } } } m_fgsArgs.pFgcParameters = m_fgcParameters; m_fgsArgs.blkSize = m_fgsBlkSize; m_fgsArgs.bitDepth = m_bitDepth; m_fgsArgs.pGrainSynt = m_grainSynt; fgsProcess(m_fgsArgs); for (compCtr = 0; compCtr < numComp; compCtr++) { delete offsetsArr[compCtr]; } return; } /* Function validates film grain parameters and returns 0 for valid parameters of SMPTE-RDD5 else 1*/ /* Also down converts the chroma model values for 4:2:0 and 4:2:2 chroma_formats */ uint8_t SEIFilmGrainSynthesizer::grainValidateParams() { uint8_t numComp = MAX_NUM_COMPONENT; /* number of color components */ uint8_t compCtr, intensityCtr, multiGrainCheck[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES] = { 0 }; uint16_t multiGrainCtr; uint8_t limitCompModelVal1[10] = { 0 }, limitCompModelVal2[10] = { 0 }; uint8_t num_comp_model_pairs = 0, limitCompModelCtr, compPairMatch; memset(m_grainSynt->intensityInterval, INTENSITY_INTERVAL_MATCH_FAIL, sizeof(m_grainSynt->intensityInterval)); if ((m_width < FG_MIN_WIDTH) || (m_width > FG_MAX_WIDTH) || (m_width % 4)) { return FGS_INVALID_WIDTH; /* Width not supported */ } if ((m_height < FG_MIN_HEIGHT) || (m_height > FG_MAX_HEIGHT) || (m_height % 4)) { return FGS_INVALID_HEIGHT; /* Height not supported */ } if ((m_chromaFormat < MIN_CHROMA_FORMAT_IDC) || (m_chromaFormat > MAX_CHROMA_FORMAT_IDC)) { return FGS_INVALID_CHROMA_FORMAT; /* Chroma format not supported */ } if (m_chromaFormat == MIN_CHROMA_FORMAT_IDC) /* Mono Chrome */ { numComp = 1; } if ((m_bitDepth < MIN_BIT_DEPTH) || (m_bitDepth > MAX_BIT_DEPTH)) { return FGS_INVALID_BIT_DEPTH; /* Bit depth not supported */ } if ((0 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag) && (1 != m_fgcParameters->m_filmGrainCharacteristicsCancelFlag)) { return FGS_INVALID_FGC_CANCEL_FLAG; /* Film grain synthesis disabled */ } if (FILM_GRAIN_MODEL_ID_VALUE != m_fgcParameters->m_filmGrainModelId) { return FGS_INVALID_GRAIN_MODEL_ID; /* Not supported */ } if (0 != m_fgcParameters->m_separateColourDescriptionPresentFlag) { return FGS_INVALID_SEP_COL_DES_FLAG; /* Not supported */ } if (BLENDING_MODE_VALUE != m_fgcParameters->m_blendingModeId) { return FGS_INVALID_BLEND_MODE; /* Not supported */ } if (m_fgcParameters->m_compModel[0].bPresentFlag || m_fgcParameters->m_compModel[1].bPresentFlag || m_fgcParameters->m_compModel[2].bPresentFlag) { if ((m_fgcParameters->m_log2ScaleFactor < MIN_LOG2SCALE_VALUE) || (m_fgcParameters->m_log2ScaleFactor > MAX_LOG2SCALE_VALUE)) { return FGS_INVALID_LOG2_SCALE_FACTOR; /* Not supported */ } } /* validation of component model present flag */ for (compCtr = 0; compCtr < numComp; compCtr++) { if ((m_fgcParameters->m_compModel[compCtr].bPresentFlag != true) && (m_fgcParameters->m_compModel[compCtr].bPresentFlag != false)) { return FGS_INVALID_COMP_MODEL_PRESENT_FLAG; /* Not supported */ } if (m_fgcParameters->m_compModel[compCtr].bPresentFlag && (m_fgcParameters->m_compModel[compCtr].numModelValues > FG_MAX_ALLOWED_MODEL_VALUES)) { return FGS_INVALID_NUM_MODEL_VALUES; /* Not supported */ } } /* validation of intensity intervals and */ for (compCtr = 0; compCtr < numComp; compCtr++) { if (m_fgcParameters->m_compModel[compCtr].bPresentFlag) { for (intensityCtr = 0; intensityCtr < m_fgcParameters->m_compModel[compCtr].intensityValues.size(); intensityCtr++) { if (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalLowerBound > m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalUpperBound) { return FGS_INVALID_INTENSITY_BOUNDARY_VALUES; /* Not supported */ } for (multiGrainCtr = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalLowerBound; multiGrainCtr <= m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].intensityIntervalUpperBound; multiGrainCtr++) { m_grainSynt->intensityInterval[compCtr][multiGrainCtr] = intensityCtr; if (multiGrainCheck[compCtr][multiGrainCtr]) /* Non over lap */ { return FGS_INVALID_INTENSITY_BOUNDARY_VALUES; /* Not supported */ } else { multiGrainCheck[compCtr][multiGrainCtr] = 1; } } m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue.resize(FG_MAX_NUM_MODEL_VALUES); /* default initialization for cut off frequencies */ if (1 == m_fgcParameters->m_compModel[compCtr].numModelValues) { m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] = DEFAULT_HORZ_CUT_OFF_FREQUENCY; m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1]; } else if (2 == m_fgcParameters->m_compModel[compCtr].numModelValues) { m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1]; } /* Error check on model component value */ if (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] > (FG_MAX_STANDARD_DEVIATION << (m_bitDepth - FG_BIT_DEPTH_8))) { return FGS_INVALID_STANDARD_DEVIATION; /* Not supported */ } else if ((m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] < MIN_CUT_OFF_FREQUENCY) || (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] > MAX_CUT_OFF_FREQUENCY)) { return FGS_INVALID_CUT_OFF_FREQUENCIES; /* Not supported */ } else if ((m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] < MIN_CUT_OFF_FREQUENCY) || (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] > MAX_CUT_OFF_FREQUENCY)) { return FGS_INVALID_CUT_OFF_FREQUENCIES; /* Not supported */ } /* conversion of component model values for 4:2:0 and 4:4:4 */ if (CHROMA_444 != m_chromaFormat && (compCtr > 0)) { if (CHROMA_420 == m_chromaFormat) /* 4:2:0 */ { m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] >>= 1; m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] = CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY, (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] << 1)); m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] = CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY, (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2] << 1)); } else if (CHROMA_422 == m_chromaFormat)/* 4:2:2 */ { m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] = (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[0] * SCALE_DOWN_422) >> Q_FORMAT_SCALING; m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] = CLIP3(MIN_CUT_OFF_FREQUENCY, MAX_CUT_OFF_FREQUENCY, (m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1] << 1)); } } compPairMatch = 0; for (limitCompModelCtr = 0; limitCompModelCtr <= num_comp_model_pairs; limitCompModelCtr++) { if ((limitCompModelVal1[limitCompModelCtr] == m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1]) && (limitCompModelVal2[limitCompModelCtr] == m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2])) { compPairMatch = 1; } } if (0 == compPairMatch) { num_comp_model_pairs++; /* max allowed pairs are 10 as per SMPTE -RDD5*/ if (num_comp_model_pairs > FG_MAX_ALLOWED_COMP_MODEL_PAIRS) { return FGS_INVALID_NUM_CUT_OFF_FREQ_PAIRS; /* Not supported */ } limitCompModelVal1[num_comp_model_pairs - 1] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[1]; limitCompModelVal2[num_comp_model_pairs - 1] = m_fgcParameters->m_compModel[compCtr].intensityValues[intensityCtr].compModelValue[2]; } } } } return FGS_SUCCESS; /* Success */ } void SEIFilmGrainSynthesizer::deriveFGSBlkSize() { uint32_t picSizeInLumaSamples = m_height * m_width; if (picSizeInLumaSamples <= (1920 * 1080)) { m_fgsBlkSize = FG_BLK_8; } else if (picSizeInLumaSamples <= (3840 * 2160)) { m_fgsBlkSize = FG_BLK_16; } else { m_fgsBlkSize = FG_BLK_32; } } void SEIFilmGrainSynthesizer::dataBaseGen() { uint32_t pseudoRandValEhv; uint8_t h, v; /* Horizaontal and vertical cut off frequencies (+2)*/ uint32_t ScaleCutOffFh, ScaleCutOffFv, l, r, i, j, k; int32_t B[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE], IDCT[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; int32_t Grain[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; const TMatrixCoeff *Tmp = g_aiT64[TRANSFORM_FORWARD][0]; const int transform_scale = 9; // upscaling of original transform as specified in VVC (for 64x64 block) const int add_1st = 1 << (transform_scale - 1); TMatrixCoeff T[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; // Original TMatrixCoeff TT[FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; // Transpose for (int x = 0; x < FG_DATA_BASE_SIZE; x++) { for (int y = 0; y < FG_DATA_BASE_SIZE; y++) { T[x][y] = Tmp[x * 64 + y]; /* Matrix Original */ TT[y][x] = Tmp[x * 64 + y]; /* Matrix Transpose */ } } for (h = 0; h < NUM_CUT_OFF_FREQ; h++) { for (v = 0; v < NUM_CUT_OFF_FREQ; v++) { memset(&B, 0, FG_DATA_BASE_SIZE*FG_DATA_BASE_SIZE * sizeof(int32_t)); memset(&IDCT, 0, FG_DATA_BASE_SIZE*FG_DATA_BASE_SIZE * sizeof(int32_t)); memset(&Grain, 0, FG_DATA_BASE_SIZE*FG_DATA_BASE_SIZE * sizeof(int32_t)); ScaleCutOffFh = ((h + 3) << 2) - 1; ScaleCutOffFv = ((v + 3) << 2) - 1; /* ehv : seed to be used for the psudo random generator for a given h and v */ pseudoRandValEhv = seedLUT[h + v * 13]; for (l = 0, r = 0; l <= ScaleCutOffFv; l++) { for (k = 0; k <= ScaleCutOffFh; k += 4) { B[k][l] = gaussianLUT[pseudoRandValEhv % 2048]; B[k + 1][l] = gaussianLUT[(pseudoRandValEhv + 1) % 2048]; B[k + 2][l] = gaussianLUT[(pseudoRandValEhv + 2) % 2048]; B[k + 3][l] = gaussianLUT[(pseudoRandValEhv + 3) % 2048]; r++; pseudoRandValEhv = prng(pseudoRandValEhv); } } B[0][0] = 0; for (i = 0; i < FG_DATA_BASE_SIZE; i++) { for (j = 0; j < FG_DATA_BASE_SIZE; j++) { for (k = 0; k < FG_DATA_BASE_SIZE; k++) { IDCT[i][j] += TT[i][k] * B[k][j]; } IDCT[i][j] += add_1st; IDCT[i][j] = IDCT[i][j] >> transform_scale; } } for (i = 0; i < FG_DATA_BASE_SIZE; i++) { for (j = 0; j < FG_DATA_BASE_SIZE; j++) { for (k = 0; k < FG_DATA_BASE_SIZE; k++) { Grain[i][j] += IDCT[i][k] * T[k][j]; } Grain[i][j] += add_1st; Grain[i][j] = Grain[i][j] >> transform_scale; m_grainSynt->dataBase[h][v][j][i] = CLIP3(-127, 127, Grain[i][j]); } } /* De-blocking at horizontal block edges */ for (l = 0; l < FG_DATA_BASE_SIZE; l += m_fgsBlkSize) { for (k = 0; k < FG_DATA_BASE_SIZE; k++) { m_grainSynt->dataBase[h][v][l][k] = ((m_grainSynt->dataBase[h][v][l][k]) * deblockFactor[v]) >> 7; m_grainSynt->dataBase[h][v][l + m_fgsBlkSize - 1][k] = ((m_grainSynt->dataBase[h][v][l + m_fgsBlkSize - 1][k]) * deblockFactor[v]) >> 7; } } } } return; } uint32_t SEIFilmGrainSynthesizer::prng(uint32_t x_r) { uint32_t addVal; addVal = (1 + ((x_r & (POS_2)) > 0) + ((x_r & (POS_30)) > 0)) % 2; x_r = (x_r << 1) + addVal; return x_r; } uint32_t SEIFilmGrainSynthesizer::fgsProcess(fgsProcessArgs &inArgs) { uint32_t errorCode; uint8_t blkSize = inArgs.blkSize; if (blkSize == 8) errorCode = fgsSimulationBlending_8x8(&inArgs); else if (blkSize == 16) errorCode = fgsSimulationBlending_16x16(&inArgs); else if (blkSize == 32) errorCode = fgsSimulationBlending_32x32(&inArgs); else errorCode = FGS_FAIL; return errorCode; } void SEIFilmGrainSynthesizer::deblockGrainStripe(Pel *grainStripe, uint32_t widthComp, uint32_t heightComp, uint32_t strideComp, uint32_t blkSize) { int32_t left1, left0, right0, right1; uint32_t pos, vertCtr; uint32_t widthCropped = (widthComp - blkSize); for (vertCtr = 0; vertCtr < heightComp; vertCtr++) { for (pos = 0; pos < widthCropped; pos += blkSize) { left1 = *(grainStripe + blkSize - 2); left0 = *(grainStripe + blkSize - 1); right0 = *(grainStripe + blkSize + 0); right1 = *(grainStripe + blkSize + 1); *(grainStripe + blkSize + 0) = (left0 + (right0 << 1) + right1) >> 2; *(grainStripe + blkSize - 1) = (left1 + (left0 << 1) + right0) >> 2; grainStripe += blkSize; } grainStripe = grainStripe + (strideComp - pos); } return; } void SEIFilmGrainSynthesizer::blendStripe(Pel *decSampleHbdOffsetY, Pel *grainStripe, uint32_t widthComp, uint32_t strideSrc, uint32_t strideGrain, uint32_t blockHeight, uint8_t bitDepth) { uint32_t k, l; uint16_t maxRange; maxRange = (1 << bitDepth) - 1; int32_t grainSample; uint16_t decodeSampleHbd; uint8_t bitDepthShift = (bitDepth - FG_BIT_DEPTH_8); uint32_t bufInc = (strideSrc - widthComp); uint32_t grainBufInc = (strideGrain - widthComp); for (l = 0; l < blockHeight; l++) /* y direction */ { for (k = 0; k < widthComp; k++) /* x direction */ { decodeSampleHbd = *decSampleHbdOffsetY; grainSample = *grainStripe; grainSample <<= bitDepthShift; grainSample = CLIP3(0, maxRange, grainSample + decodeSampleHbd); *decSampleHbdOffsetY = (Pel)grainSample; decSampleHbdOffsetY++; grainStripe++; } decSampleHbdOffsetY += bufInc; grainStripe += grainBufInc; } return; } void SEIFilmGrainSynthesizer::blendStripe_32x32(Pel *decSampleHbdOffsetY, Pel *grainStripe, uint32_t widthComp, uint32_t strideSrc, uint32_t strideGrain, uint32_t blockHeight, uint8_t bitDepth) { uint32_t k, l; uint16_t maxRange; maxRange = (1 << bitDepth) - 1; int32_t grainSample; uint16_t decodeSampleHbd; uint8_t bitDepthShift = (bitDepth - FG_BIT_DEPTH_8); uint32_t bufInc = (strideSrc - widthComp); uint32_t grainBufInc = (strideGrain - widthComp); for (l = 0; l < blockHeight; l++) /* y direction */ { for (k = 0; k < widthComp; k++) /* x direction */ { decodeSampleHbd = *decSampleHbdOffsetY; grainSample = *grainStripe; grainSample <<= bitDepthShift; grainSample = CLIP3(0, maxRange, grainSample + decodeSampleHbd); *decSampleHbdOffsetY = (Pel)grainSample; decSampleHbdOffsetY++; grainStripe++; } decSampleHbdOffsetY += bufInc; grainStripe += grainBufInc; } return; } Pel SEIFilmGrainSynthesizer::blockAverage_8x8(Pel *decSampleBlk8, uint32_t widthComp, uint16_t *pNumSamples, uint8_t ySize, uint8_t xSize, uint8_t bitDepth) { uint32_t blockAvg = 0; uint8_t k; uint8_t l; for (k = 0; k < ySize; k++) { for (l = 0; l < xSize; l++) { blockAvg += *decSampleBlk8; decSampleBlk8++; } decSampleBlk8 += widthComp - xSize; } blockAvg = blockAvg >> (FG_BLK_8_shift + (bitDepth - FG_BIT_DEPTH_8)); *pNumSamples = FG_BLK_AREA_8x8; return blockAvg; } uint32_t SEIFilmGrainSynthesizer::blockAverage_16x16(Pel *decSampleBlk8, uint32_t widthComp, uint16_t *pNumSamples, uint8_t ySize, uint8_t xSize, uint8_t bitDepth) { uint32_t blockAvg = 0; uint8_t k; uint8_t l; for (k = 0; k < ySize; k++) { for (l = 0; l < xSize; l++) { blockAvg += *decSampleBlk8; decSampleBlk8++; } decSampleBlk8 += widthComp - xSize; } // blockAvg = blockAvg >> (FG_BLK_16_shift + (bitDepth - FG_BIT_DEPTH_8)); // If FG_BLK_16 is not used or changed FG_BLK_AREA_16x16 has to be changed *pNumSamples = FG_BLK_AREA_16x16; return blockAvg; } uint32_t SEIFilmGrainSynthesizer::blockAverage_32x32(Pel *decSampleBlk32, uint32_t strideComp, uint8_t bitDepth) { uint32_t blockAvg = 0; uint8_t k; uint8_t l; uint32_t bufInc = strideComp - FG_BLK_32; for (k = 0; k < FG_BLK_32; k++) { for (l = 0; l < FG_BLK_32; l++) { blockAvg += *decSampleBlk32++; } decSampleBlk32 += bufInc; } blockAvg = blockAvg >> (FG_BLK_32_shift + (bitDepth - FG_BIT_DEPTH_8)); return blockAvg; } void SEIFilmGrainSynthesizer::simulateGrainBlk8x8(Pel *grainStripe, uint32_t grainStripeOffsetBlk8, GrainSynthesisStruct *grain_synt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize) { uint32_t l; int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset]; grainStripe += grainStripeOffsetBlk8; uint32_t k; for (l = 0; l < FG_BLK_8; l++) /* y direction */ { for (k = 0; k < xSize; k++) /* x direction */ { *grainStripe = ((scaleFactor * (*database_h_v)) >> (log2ScaleFactor + GRAIN_SCALE)); grainStripe++; database_h_v++; } grainStripe += width - xSize; database_h_v += FG_DATA_BASE_SIZE - xSize; } return; } void SEIFilmGrainSynthesizer::simulateGrainBlk16x16(Pel *grainStripe, uint32_t grainStripeOffsetBlk8, GrainSynthesisStruct *grain_synt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize) { uint32_t l; int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset]; grainStripe += grainStripeOffsetBlk8; uint32_t k; for (l = 0; l < FG_BLK_16; l++) /* y direction */ { for (k = 0; k < xSize; k++) /* x direction */ { *grainStripe = (int16_t)(((int32_t)scaleFactor * (*database_h_v)) >> (log2ScaleFactor + GRAIN_SCALE)); grainStripe++; database_h_v++; } grainStripe += width - xSize; database_h_v += FG_DATA_BASE_SIZE - xSize; } return; } void SEIFilmGrainSynthesizer::simulateGrainBlk32x32(Pel *grainStripe, uint32_t grainStripeOffsetBlk32, GrainSynthesisStruct *grain_synt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v) { uint32_t l; int8_t * database_h_v = &grain_synt->dataBase[h][v][lOffset][kOffset]; grainStripe += grainStripeOffsetBlk32; uint32_t k; uint8_t shiftVal = log2ScaleFactor + GRAIN_SCALE; uint32_t grainbufInc = width - FG_BLK_32; for (l = 0; l < FG_BLK_32; l++) /* y direction */ { for (k = 0; k < FG_BLK_32; k++) /* x direction */ { *grainStripe = ((scaleFactor * (*database_h_v)) >> shiftVal); grainStripe++; database_h_v++; } grainStripe += grainbufInc; database_h_v += FG_DATA_BASE_SIZE - FG_BLK_32; } return; } uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_8x8(fgsProcessArgs *inArgs) { uint8_t numComp, compCtr, blkId; /* number of color components */ uint8_t log2ScaleFactor, h, v; uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */ uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT], strideComp[MAX_NUM_COMPONENT]; Pel * decSampleHbdBlk16, *decSampleHbdBlk8, *decSampleHbdOffsetY; Pel * decHbdComp[MAX_NUM_COMPONENT]; uint16_t numSamples; int16_t scaleFactor; uint32_t kOffset, lOffset, grainStripeOffset, grainStripeOffsetBlk8, offsetBlk8x8; uint32_t kOffset_const, lOffset_const; int16_t scaleFactor_const; Pel * grainStripe; /* worth a row of 16x16 : Max size : 16xw;*/ int32_t yOffset8x8, xOffset8x8; uint32_t x, y; uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */ uint32_t grainStripeWidth; uint32_t wdPadded; bitDepth = inArgs->bitDepth; numComp = inArgs->numComp; log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor; for (compCtr = 0; compCtr < numComp; compCtr++) { decHbdComp[compCtr] = inArgs->decComp[compCtr]; strideComp[compCtr] = inArgs->strideComp[compCtr]; widthComp[compCtr] = inArgs->widthComp[compCtr]; heightComp[compCtr] = inArgs->heightComp[compCtr]; } wdPadded = ((inArgs->widthComp[0] - 1) | 0xF) + 1; grainStripe = new Pel[wdPadded * FG_BLK_16]; if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag) { for (compCtr = 0; compCtr < numComp; compCtr++) { if (1 == inArgs->pFgcParameters->m_compModel[compCtr].bPresentFlag) { decSampleHbdOffsetY = decHbdComp[compCtr]; uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr]; grainStripeWidth = ((widthComp[compCtr] - 1) | 0xF) + 1; // Make next muliptle of 16 /* Loop of 16x16 blocks */ for (y = 0; y < heightComp[compCtr]; y += FG_BLK_16) { /* Initialization of grain stripe of 16xwidth size */ memset(grainStripe, 0, (grainStripeWidth * FG_BLK_16 * sizeof(Pel))); for (x = 0; x < widthComp[compCtr]; x += FG_BLK_16) { /* start position offset of decoded sample in x direction */ grainStripeOffset = x; decSampleHbdBlk16 = decSampleHbdOffsetY + x; kOffset_const = (MSB16(*offset_tmp) % 52); kOffset_const &= 0xFFFC; lOffset_const = (LSB16(*offset_tmp) % 56); lOffset_const &= 0xFFF8; scaleFactor_const = 1 - 2 * BIT0(*offset_tmp); for (blkId = 0; blkId < NUM_8x8_BLKS_16x16; blkId++) { yOffset8x8 = (blkId >> 1) * FG_BLK_8; xOffset8x8 = (blkId & 0x1) * FG_BLK_8; offsetBlk8x8 = xOffset8x8 + (yOffset8x8 * strideComp[compCtr]); grainStripeOffsetBlk8 = grainStripeOffset + (xOffset8x8 + (yOffset8x8 * grainStripeWidth)); decSampleHbdBlk8 = decSampleHbdBlk16 + offsetBlk8x8; blockAvg = blockAverage_8x8(decSampleHbdBlk8, strideComp[compCtr], &numSamples, FG_BLK_8, FG_BLK_8, bitDepth); /* Selection of the component model */ intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg]; if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt) { /* 8x8 grain block offset using co-ordinates of decoded 8x8 block in the frame */ // kOffset = kOffset_const; kOffset = kOffset_const + xOffset8x8; lOffset = lOffset_const + yOffset8x8; scaleFactor = scaleFactor_const * inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0]; h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2; v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2; /* 8x8 block grain simulation */ simulateGrainBlk8x8(grainStripe, grainStripeOffsetBlk8, inArgs->pGrainSynt, grainStripeWidth, log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v, FG_BLK_8); } /* only if average falls in any interval */ // }/* includes corner case handling */ } /* 8x8 level block processing */ /* uppdate the PRNG once per 16x16 block of samples */ offset_tmp++; } /* End of 16xwidth grain simulation */ /* deblocking at the vertical edges of 8x8 at 16xwidth*/ deblockGrainStripe(grainStripe, widthComp[compCtr], FG_BLK_16, grainStripeWidth, FG_BLK_8); /* Blending of size 16xwidth*/ blendStripe(decSampleHbdOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth, FG_BLK_16, bitDepth); decSampleHbdOffsetY += FG_BLK_16 * strideComp[compCtr]; } /* end of component loop */ } } } delete grainStripe; return FGS_SUCCESS; } uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_16x16(fgsProcessArgs *inArgs) { uint8_t numComp, compCtr; /* number of color components */ uint8_t log2ScaleFactor, h, v; uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */ uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT], strideComp[MAX_NUM_COMPONENT]; Pel * decSampleHbdBlk16, *decSampleHbdOffsetY; Pel * decHbdComp[MAX_NUM_COMPONENT]; uint16_t numSamples; int16_t scaleFactor; uint32_t kOffset, lOffset, grainStripeOffset; Pel * grainStripe; /* worth a row of 16x16 : Max size : 16xw;*/ uint32_t x, y; uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */ uint32_t grainStripeWidth; uint32_t wdPadded; bitDepth = inArgs->bitDepth; numComp = inArgs->numComp; log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor; for (compCtr = 0; compCtr < numComp; compCtr++) { decHbdComp[compCtr] = inArgs->decComp[compCtr]; strideComp[compCtr] = inArgs->strideComp[compCtr]; widthComp[compCtr] = inArgs->widthComp[compCtr]; heightComp[compCtr] = inArgs->heightComp[compCtr]; } wdPadded = ((inArgs->widthComp[0] - 1) | 0xF) + 1; grainStripe = new Pel[wdPadded * FG_BLK_16]; if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag) { for (compCtr = 0; compCtr < numComp; compCtr++) { if (1 == inArgs->pFgcParameters->m_compModel[compCtr].bPresentFlag) { decSampleHbdOffsetY = decHbdComp[compCtr]; uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr]; grainStripeWidth = ((widthComp[compCtr] - 1) | 0xF) + 1; // Make next muliptle of 16 /* Loop of 16x16 blocks */ for (y = 0; y < heightComp[compCtr]; y += FG_BLK_16) { /* Initialization of grain stripe of 16xwidth size */ memset(grainStripe, 0, (grainStripeWidth * FG_BLK_16 * sizeof(Pel))); for (x = 0; x < widthComp[compCtr]; x += FG_BLK_16) { /* start position offset of decoded sample in x direction */ grainStripeOffset = x; decSampleHbdBlk16 = decSampleHbdOffsetY + x; blockAvg = blockAverage_16x16(decSampleHbdBlk16, strideComp[compCtr], &numSamples, FG_BLK_16, FG_BLK_16, bitDepth); blockAvg = blockAvg >> (FG_BLK_16_shift + (bitDepth - FG_BIT_DEPTH_8)); /* Selection of the component model */ intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg]; if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt) { kOffset = (MSB16(*offset_tmp) % 52); kOffset &= 0xFFFC; lOffset = (LSB16(*offset_tmp) % 56); lOffset &= 0xFFF8; scaleFactor = 1 - 2 * BIT0(*offset_tmp); scaleFactor *= inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0]; h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2; v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2; /* 16x16 block grain simulation */ simulateGrainBlk16x16(grainStripe, grainStripeOffset, inArgs->pGrainSynt, grainStripeWidth, log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v, FG_BLK_16); } /* only if average falls in any interval */ // }/* includes corner case handling */ /* uppdate the PRNG once per 16x16 block of samples */ offset_tmp++; } /* End of 16xwidth grain simulation */ /* deblocking at the vertical edges of 16x16 at 16xwidth*/ deblockGrainStripe(grainStripe, widthComp[compCtr], FG_BLK_16, grainStripeWidth, FG_BLK_16); /* Blending of size 16xwidth*/ blendStripe(decSampleHbdOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth, FG_BLK_16, bitDepth); decSampleHbdOffsetY += FG_BLK_16 * strideComp[compCtr]; } /* end of component loop */ } } } delete grainStripe; return FGS_SUCCESS; } uint32_t SEIFilmGrainSynthesizer::fgsSimulationBlending_32x32(fgsProcessArgs *inArgs) { uint8_t numComp, compCtr; /* number of color components */ uint8_t log2ScaleFactor, h, v; uint8_t bitDepth; /*grain bit depth and decoded bit depth are assumed to be same */ uint32_t widthComp[MAX_NUM_COMPONENT], heightComp[MAX_NUM_COMPONENT], strideComp[MAX_NUM_COMPONENT]; Pel * decSampleBlk32, *decSampleOffsetY; Pel * decComp[MAX_NUM_COMPONENT]; int16_t scaleFactor; uint32_t kOffset, lOffset, grainStripeOffset; Pel * grainStripe; uint32_t x, y; uint32_t blockAvg, intensityInt; /* ec : seed to be used for the psudo random generator for a given color component */ uint32_t grainStripeWidth; uint32_t wdPadded; bitDepth = inArgs->bitDepth; numComp = inArgs->numComp; log2ScaleFactor = inArgs->pFgcParameters->m_log2ScaleFactor; for (compCtr = 0; compCtr < numComp; compCtr++) { decComp[compCtr] = inArgs->decComp[compCtr]; strideComp[compCtr] = inArgs->strideComp[compCtr]; heightComp[compCtr] = inArgs->heightComp[compCtr]; widthComp[compCtr] = inArgs->widthComp[compCtr]; } wdPadded = ((inArgs->widthComp[0] - 1) | 0x1F) + 1; grainStripe = new Pel[wdPadded * FG_BLK_32]; if (0 == inArgs->pFgcParameters->m_filmGrainCharacteristicsCancelFlag) { for (compCtr = 0; compCtr < numComp; compCtr++) { if (1 == inArgs->pFgcParameters->m_compModel[compCtr].bPresentFlag) { uint32_t *offset_tmp = inArgs->fgsOffsets[compCtr]; decSampleOffsetY = decComp[compCtr]; grainStripeWidth = ((widthComp[compCtr] - 1) | 0x1F) + 1; // Make next muliptle of 32 /* Loop of 32x32 blocks */ for (y = 0; y < heightComp[compCtr]; y += FG_BLK_32) { /* Initialization of grain stripe of 32xwidth size */ memset(grainStripe, 0, (grainStripeWidth * FG_BLK_32 * sizeof(Pel))); for (x = 0; x < widthComp[compCtr]; x += FG_BLK_32) { /* start position offset of decoded sample in x direction */ grainStripeOffset = x; decSampleBlk32 = decSampleOffsetY + x; blockAvg = blockAverage_32x32(decSampleBlk32, strideComp[compCtr], bitDepth); /* Selection of the component model */ intensityInt = inArgs->pGrainSynt->intensityInterval[compCtr][blockAvg]; if (INTENSITY_INTERVAL_MATCH_FAIL != intensityInt) { kOffset = (MSB16(*offset_tmp) % 36); kOffset &= 0xFFFC; lOffset = (LSB16(*offset_tmp) % 40); lOffset &= 0xFFF8; scaleFactor = 1 - 2 * BIT0(*offset_tmp); scaleFactor *= inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[0]; h = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[1] - 2; v = inArgs->pFgcParameters->m_compModel[compCtr].intensityValues[intensityInt].compModelValue[2] - 2; /* 32x32 block grain simulation */ simulateGrainBlk32x32(grainStripe, grainStripeOffset, inArgs->pGrainSynt, grainStripeWidth, log2ScaleFactor, scaleFactor, kOffset, lOffset, h, v); } /* only if average falls in any interval */ /* uppdate the PRNG once per 16x16 block of samples */ offset_tmp++; } /* End of 32xwidth grain simulation */ /* deblocking at the vertical edges of 8x8 at 16xwidth*/ deblockGrainStripe(grainStripe, widthComp[compCtr], FG_BLK_32, grainStripeWidth, FG_BLK_32); blendStripe_32x32(decSampleOffsetY, grainStripe, widthComp[compCtr], strideComp[compCtr], grainStripeWidth, FG_BLK_32, bitDepth); decSampleOffsetY += FG_BLK_32 * strideComp[compCtr]; } /* end of component loop */ } } } delete grainStripe; return FGS_SUCCESS; } #endif HM-HM-18.0/source/Lib/TLibCommon/SEIFilmGrainSynthesizer.h000066400000000000000000000250561442026013100231140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIFilmGrainSynthesizer.h \brief SMPTE RDD5 based film grain synthesis functionality from SEI messages */ #ifndef __SEIFILMGRAINSYNTHESIZER__ #define __SEIFILMGRAINSYNTHESIZER__ #include "SEI.h" #include "TComPicYuv.h" #if JVET_X0048_X0103_FILM_GRAIN //! \ingroup SEIFilmGrainSynthesizer //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== static const int MIN_LOG2SCALE_VALUE = 2; static const int MAX_LOG2SCALE_VALUE = 7; static const int FILM_GRAIN_MODEL_ID_VALUE = 0; static const int BLENDING_MODE_VALUE = 0; static const int MIN_CUT_OFF_FREQUENCY = 2; static const int MAX_CUT_OFF_FREQUENCY = 14; static const int DEFAULT_HORZ_CUT_OFF_FREQUENCY = 8; static const int NUM_CUT_OFF_FREQ = 13; static const int SCALE_DOWN_422 = 181; /* in Q-format of 8 : 1/sqrt(2) */ static const int Q_FORMAT_SCALING = 8; static const int GRAIN_SCALE = 6; static const int MIN_CHROMA_FORMAT_IDC = 0; static const int MAX_CHROMA_FORMAT_IDC = 3; static const int MIN_BIT_DEPTH = 8; static const int MAX_BIT_DEPTH = 16; static const int FG_BLK_8_shift = 6; static const int FG_BLK_16_shift = 8; static const int FG_BLK_32_shift = 10; static const int NUM_8x8_BLKS_16x16 = 4; static const int NUM_16x16_BLKS_32x32 = 4; static const int FG_BLK_AREA_8x8 = 64; static const int FG_BLK_AREA_16x16 = 256; static const int INTENSITY_INTERVAL_MATCH_FAIL = -1; static const int COLOUR_OFFSET_LUMA = 0; static const int COLOUR_OFFSET_CR = 85; static const int COLOUR_OFFSET_CB = 170; static const int FG_MIN_WIDTH = 128; static const int FG_MAX_WIDTH = 7680; static const int FG_MIN_HEIGHT = 128; static const int FG_MAX_HEIGHT = 4320; #define CLIP3(min, max, x) (((x) > (max)) ? (max) :(((x) < (min))? (min):(x))) #define MIN(x,y) (((x) > (y)) ? (y) : (x)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) #define MSB16(x) ((x&0xFFFF0000)>>16) #define LSB16(x) (x&0x0000FFFF) #define BIT0(x) (x&0x1) #define POS_30 (1<<30) #define POS_2 (1<<2) /* Error start codes for various classes of errors */ #define FGS_FILE_IO_ERROR 0x0010 #define FGS_PARAM_ERROR 0x0020 /* Error codes for various errors in SMPTE-RDD5 standalone grain synthesizer */ typedef enum { /* No error */ FGS_SUCCESS = 0, /* Invalid input width */ FGS_INVALID_WIDTH = FGS_FILE_IO_ERROR + 0x01, /* Invalid input height */ FGS_INVALID_HEIGHT = FGS_FILE_IO_ERROR + 0x02, /* Invalid Chroma format idc */ FGS_INVALID_CHROMA_FORMAT = FGS_FILE_IO_ERROR + 0x03, /* Invalid bit depth */ FGS_INVALID_BIT_DEPTH = FGS_FILE_IO_ERROR + 0x04, /* Invalid Film grain characteristic cancel flag */ FGS_INVALID_FGC_CANCEL_FLAG = FGS_PARAM_ERROR + 0x01, /* Invalid film grain model id */ FGS_INVALID_GRAIN_MODEL_ID = FGS_PARAM_ERROR + 0x02, /* Invalid separate color description present flag */ FGS_INVALID_SEP_COL_DES_FLAG = FGS_PARAM_ERROR + 0x03, /* Invalid blending mode */ FGS_INVALID_BLEND_MODE = FGS_PARAM_ERROR + 0x04, /* Invalid log_2_scale_factor value */ FGS_INVALID_LOG2_SCALE_FACTOR = FGS_PARAM_ERROR + 0x05, /* Invalid component model present flag */ FGS_INVALID_COMP_MODEL_PRESENT_FLAG = FGS_PARAM_ERROR + 0x06, /* Invalid number of model values */ FGS_INVALID_NUM_MODEL_VALUES = FGS_PARAM_ERROR + 0x07, /* Invalid bound values, overlapping boundaries */ FGS_INVALID_INTENSITY_BOUNDARY_VALUES = FGS_PARAM_ERROR + 0x08, /* Invalid standard deviation */ FGS_INVALID_STANDARD_DEVIATION = FGS_PARAM_ERROR + 0x09, /* Invalid cut off frequencies */ FGS_INVALID_CUT_OFF_FREQUENCIES = FGS_PARAM_ERROR + 0x0A, /* Invalid number of cut off frequency pairs */ FGS_INVALID_NUM_CUT_OFF_FREQ_PAIRS = FGS_PARAM_ERROR + 0x0B, /* Invalid film grain characteristics repetition period */ FGS_INVALID_FGC_REPETETION_PERIOD = FGS_PARAM_ERROR + 0x0C, /* Failure error code */ FGS_FAIL = 0xFF }FGS_ERROR_T; /* FGC Error Codes END */ typedef struct GrainSynthesisStruct_t { int8_t dataBase[NUM_CUT_OFF_FREQ][NUM_CUT_OFF_FREQ][FG_DATA_BASE_SIZE][FG_DATA_BASE_SIZE]; int16_t intensityInterval[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; }GrainSynthesisStruct; typedef struct fgsProcessArgs { uint8_t numComp; uint32_t * fgsOffsets[MAX_NUM_COMPONENT]; Pel * decComp[MAX_NUM_COMPONENT]; uint32_t widthComp[MAX_NUM_COMPONENT]; uint32_t heightComp[MAX_NUM_COMPONENT]; uint32_t strideComp[MAX_NUM_COMPONENT]; SEIFilmGrainCharacteristics *pFgcParameters; GrainSynthesisStruct * pGrainSynt; uint8_t bitDepth; uint8_t blkSize; } fgsProcessArgs; class SEIFilmGrainSynthesizer { private: uint32_t m_width; uint32_t m_height; ChromaFormat m_chromaFormat; uint8_t m_bitDepth; uint32_t m_idrPicId; fgsProcessArgs m_fgsArgs; GrainSynthesisStruct *m_grainSynt; uint8_t m_fgsBlkSize; public: uint32_t m_poc; int32_t m_errorCode; SEIFilmGrainCharacteristics *m_fgcParameters; public: SEIFilmGrainSynthesizer(); virtual ~SEIFilmGrainSynthesizer(); void create(uint32_t width, uint32_t height, ChromaFormat fmt, uint8_t bitDepth, uint32_t idrPicId); void destroy (); void fgsInit (); void grainSynthesizeAndBlend(TComPicYuv* pGrainBuf, Bool isIdrPic); uint8_t grainValidateParams(); private: void deriveFGSBlkSize (); void dataBaseGen (); static uint32_t prng (uint32_t x_r); static uint32_t fgsProcess (fgsProcessArgs &inArgs); static void deblockGrainStripe (Pel *grainStripe, uint32_t widthComp, uint32_t heightComp, uint32_t strideComp, uint32_t blkSize); static void blendStripe (Pel *decSampleOffsetY, Pel *grainStripe, uint32_t widthComp, uint32_t strideSrc, uint32_t strideGrain, uint32_t blockHeight, uint8_t bitDepth); static void blendStripe_32x32 (Pel *decSampleOffsetY, Pel *grainStripe, uint32_t widthComp, uint32_t strideSrc, uint32_t strideGrain, uint32_t blockHeight, uint8_t bitDepth); static Pel blockAverage_8x8 (Pel *decSampleBlk8, uint32_t widthComp, uint16_t *pNumSamples, uint8_t ySize, uint8_t xSize, uint8_t bitDepth); static uint32_t blockAverage_16x16 (Pel *decSampleBlk8, uint32_t widthComp, uint16_t *pNumSamples, uint8_t ySize, uint8_t xSize, uint8_t bitDepth); static uint32_t blockAverage_32x32 (Pel *decSampleBlk32, uint32_t strideComp, uint8_t bitDepth); static void simulateGrainBlk8x8 (Pel *grainStripe, uint32_t grainStripeOffsetBlk8, GrainSynthesisStruct *pGrainSynt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize); static void simulateGrainBlk16x16(Pel *grainStripe, uint32_t grainStripeOffsetBlk8, GrainSynthesisStruct *grain_synt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v, uint32_t xSize); static void simulateGrainBlk32x32(Pel *grainStripe, uint32_t grainStripeOffsetBlk32, GrainSynthesisStruct *grain_synt, uint32_t width, uint8_t log2ScaleFactor, int16_t scaleFactor, uint32_t kOffset, uint32_t lOffset, uint8_t h, uint8_t v); static uint32_t fgsSimulationBlending_8x8 (fgsProcessArgs *inArgs); static uint32_t fgsSimulationBlending_16x16 (fgsProcessArgs *inArgs); static uint32_t fgsSimulationBlending_32x32 (fgsProcessArgs *inArgs); };// END CLASS DEFINITION SEIFilmGrainSynthesizer //! \} #endif #endif // __SEIFILMGRAINSYNTHESIZER__ HM-HM-18.0/source/Lib/TLibCommon/TComBitCounter.h000066400000000000000000000056761442026013100213020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComBitCounter.h \brief Class for counting bits (header) */ #ifndef __TCOMBITCOUNTER__ #define __TCOMBITCOUNTER__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TComBitStream.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// class for counting bits class TComBitCounter : public TComBitIf { protected: UInt m_uiBitCounter; public: TComBitCounter() {} virtual ~TComBitCounter() {} Void write ( UInt /*uiBits*/, UInt uiNumberOfBits ) { m_uiBitCounter += uiNumberOfBits; } Void resetBits () { m_uiBitCounter = 0; } UInt getNumberOfWrittenBits() const { return m_uiBitCounter; } Int getNumBitsUntilByteAligned() const { return (8 - m_uiBitCounter) & 0x7;} }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComBitStream.cpp000066400000000000000000000276451442026013100214510ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComBitStream.cpp \brief class for handling bitstream */ #include #include #include "TComBitStream.h" #include #include using namespace std; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TComOutputBitstream::TComOutputBitstream() { clear(); } TComOutputBitstream::~TComOutputBitstream() { } TComInputBitstream::TComInputBitstream() : m_fifo() , m_emulationPreventionByteLocation() , m_fifo_idx(0) , m_num_held_bits(0) , m_held_bits(0) , m_numBitsRead(0) { } TComInputBitstream::TComInputBitstream(const TComInputBitstream &src) : m_fifo(src.m_fifo) , m_emulationPreventionByteLocation(src.m_emulationPreventionByteLocation) , m_fifo_idx(src.m_fifo_idx) , m_num_held_bits(src.m_num_held_bits) , m_held_bits(src.m_held_bits) , m_numBitsRead(src.m_numBitsRead) { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TComInputBitstream::resetToStart() { m_fifo_idx=0; m_num_held_bits=0; m_held_bits=0; m_numBitsRead=0; } UChar* TComOutputBitstream::getByteStream() const { return (UChar*) &m_fifo.front(); } UInt TComOutputBitstream::getByteStreamLength() { return UInt(m_fifo.size()); } Void TComOutputBitstream::clear() { m_fifo.clear(); m_held_bits = 0; m_num_held_bits = 0; } Void TComOutputBitstream::write ( UInt uiBits, UInt uiNumberOfBits ) { assert( uiNumberOfBits <= 32 ); assert( uiNumberOfBits == 32 || (uiBits & (~0 << uiNumberOfBits)) == 0 ); /* any modulo 8 remainder of num_total_bits cannot be written this time, * and will be held until next time. */ UInt num_total_bits = uiNumberOfBits + m_num_held_bits; UInt next_num_held_bits = num_total_bits % 8; /* form a byte aligned word (write_bits), by concatenating any held bits * with the new bits, discarding the bits that will form the next_held_bits. * eg: H = held bits, V = n new bits /---- next_held_bits * len(H)=7, len(V)=1: ... ---- HHHH HHHV . 0000 0000, next_num_held_bits=0 * len(H)=7, len(V)=2: ... ---- HHHH HHHV . V000 0000, next_num_held_bits=1 * if total_bits < 8, the value of v_ is not used */ UChar next_held_bits = uiBits << (8 - next_num_held_bits); if (!(num_total_bits >> 3)) { /* insufficient bits accumulated to write out, append new_held_bits to * current held_bits */ /* NB, this requires that v only contains 0 in bit positions {31..n} */ m_held_bits |= next_held_bits; m_num_held_bits = next_num_held_bits; return; } /* topword serves to justify held_bits to align with the msb of uiBits */ UInt topword = (uiNumberOfBits - next_num_held_bits) & ~((1 << 3) -1); UInt write_bits = (m_held_bits << topword) | (uiBits >> next_num_held_bits); switch (num_total_bits >> 3) { case 4: m_fifo.push_back(write_bits >> 24); case 3: m_fifo.push_back(write_bits >> 16); case 2: m_fifo.push_back(write_bits >> 8); case 1: m_fifo.push_back(write_bits); } m_held_bits = next_held_bits; m_num_held_bits = next_num_held_bits; } Void TComOutputBitstream::writeAlignOne() { UInt num_bits = getNumBitsUntilByteAligned(); write((1 << num_bits) - 1, num_bits); return; } Void TComOutputBitstream::writeAlignZero() { if (0 == m_num_held_bits) { return; } m_fifo.push_back(m_held_bits); m_held_bits = 0; m_num_held_bits = 0; } /** - add substream to the end of the current bitstream . \param pcSubstream substream to be added */ Void TComOutputBitstream::addSubstream( TComOutputBitstream* pcSubstream ) { UInt uiNumBits = pcSubstream->getNumberOfWrittenBits(); const vector& rbsp = pcSubstream->getFIFO(); for (vector::const_iterator it = rbsp.begin(); it != rbsp.end();) { write(*it++, 8); } if (uiNumBits&0x7) { write(pcSubstream->getHeldBits()>>(8-(uiNumBits&0x7)), uiNumBits&0x7); } } Void TComOutputBitstream::writeByteAlignment() { write( 1, 1); writeAlignZero(); } Int TComOutputBitstream::countStartCodeEmulations() { UInt cnt = 0; vector& rbsp = getFIFO(); for (vector::iterator it = rbsp.begin(); it != rbsp.end();) { vector::iterator found = it; do { // find the next emulated 00 00 {00,01,02,03} // NB, end()-1, prevents finding a trailing two byte sequence found = search_n(found, rbsp.end()-1, 2, 0); found++; // if not found, found == end, otherwise found = second zero byte if (found == rbsp.end()) { break; } if (*(++found) <= 3) { break; } } while (true); it = found; if (found != rbsp.end()) { cnt++; } } return cnt; } /** * read uiNumberOfBits from bitstream without updating the bitstream * state, storing the result in ruiBits. * * If reading uiNumberOfBits would overrun the bitstream buffer, * the bitstream is effectively padded with sufficient zero-bits to * avoid the overrun. */ Void TComInputBitstream::pseudoRead ( UInt uiNumberOfBits, UInt& ruiBits ) { UInt saved_num_held_bits = m_num_held_bits; UChar saved_held_bits = m_held_bits; UInt saved_fifo_idx = m_fifo_idx; UInt num_bits_to_read = min(uiNumberOfBits, getNumBitsLeft()); read(num_bits_to_read, ruiBits); ruiBits <<= (uiNumberOfBits - num_bits_to_read); m_fifo_idx = saved_fifo_idx; m_held_bits = saved_held_bits; m_num_held_bits = saved_num_held_bits; } Void TComInputBitstream::read (UInt uiNumberOfBits, UInt& ruiBits) { assert( uiNumberOfBits <= 32 ); m_numBitsRead += uiNumberOfBits; /* NB, bits are extracted from the MSB of each byte. */ UInt retval = 0; if (uiNumberOfBits <= m_num_held_bits) { /* n=1, len(H)=7: -VHH HHHH, shift_down=6, mask=0xfe * n=3, len(H)=7: -VVV HHHH, shift_down=4, mask=0xf8 */ retval = m_held_bits >> (m_num_held_bits - uiNumberOfBits); retval &= ~(0xff << uiNumberOfBits); m_num_held_bits -= uiNumberOfBits; ruiBits = retval; return; } /* all num_held_bits will go into retval * => need to mask leftover bits from previous extractions * => align retval with top of extracted word */ /* n=5, len(H)=3: ---- -VVV, mask=0x07, shift_up=5-3=2, * n=9, len(H)=3: ---- -VVV, mask=0x07, shift_up=9-3=6 */ uiNumberOfBits -= m_num_held_bits; retval = m_held_bits & ~(0xff << m_num_held_bits); retval <<= uiNumberOfBits; /* number of whole bytes that need to be loaded to form retval */ /* n=32, len(H)=0, load 4bytes, shift_down=0 * n=32, len(H)=1, load 4bytes, shift_down=1 * n=31, len(H)=1, load 4bytes, shift_down=1+1 * n=8, len(H)=0, load 1byte, shift_down=0 * n=8, len(H)=3, load 1byte, shift_down=3 * n=5, len(H)=1, load 1byte, shift_down=1+3 */ UInt aligned_word = 0; UInt num_bytes_to_load = (uiNumberOfBits - 1) >> 3; assert(m_fifo_idx + num_bytes_to_load < m_fifo.size()); switch (num_bytes_to_load) { case 3: aligned_word = m_fifo[m_fifo_idx++] << 24; case 2: aligned_word |= m_fifo[m_fifo_idx++] << 16; case 1: aligned_word |= m_fifo[m_fifo_idx++] << 8; case 0: aligned_word |= m_fifo[m_fifo_idx++]; } /* resolve remainder bits */ UInt next_num_held_bits = (32 - uiNumberOfBits) % 8; /* copy required part of aligned_word into retval */ retval |= aligned_word >> next_num_held_bits; /* store held bits */ m_num_held_bits = next_num_held_bits; m_held_bits = aligned_word; ruiBits = retval; } /** * insert the contents of the bytealigned (and flushed) bitstream src * into this at byte position pos. */ Void TComOutputBitstream::insertAt(const TComOutputBitstream& src, UInt pos) { UInt src_bits = src.getNumberOfWrittenBits(); assert(0 == src_bits % 8); vector::iterator at = m_fifo.begin() + pos; m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end()); } UInt TComInputBitstream::readOutTrailingBits () { UInt count=0; UInt uiBits = 0; while ( ( getNumBitsLeft() > 0 ) && (getNumBitsUntilByteAligned()!=0) ) { count++; read ( 1, uiBits ); } return count; } // //TComOutputBitstream& TComOutputBitstream::operator= (const TComOutputBitstream& src) //{ // vector::iterator at = m_fifo.begin(); // m_fifo.insert(at, src.m_fifo.begin(), src.m_fifo.end()); // // m_num_held_bits = src.m_num_held_bits; // m_held_bits = src.m_held_bits; // // return *this; //} /** Extract substream from the current bitstream. \param uiNumBits number of bits to transfer */ TComInputBitstream *TComInputBitstream::extractSubstream( UInt uiNumBits ) { UInt uiNumBytes = uiNumBits/8; TComInputBitstream *pResult = new TComInputBitstream; std::vector &buf = pResult->getFifo(); buf.reserve((uiNumBits+7)>>3); if (m_num_held_bits == 0) { std::size_t currentOutputBufferSize=buf.size(); const UInt uiNumBytesToReadFromFifo = std::min(uiNumBytes, (UInt)m_fifo.size() - m_fifo_idx); buf.resize(currentOutputBufferSize+uiNumBytes); memcpy(&(buf[currentOutputBufferSize]), &(m_fifo[m_fifo_idx]), uiNumBytesToReadFromFifo); m_fifo_idx+=uiNumBytesToReadFromFifo; if (uiNumBytesToReadFromFifo != uiNumBytes) { memset(&(buf[currentOutputBufferSize+uiNumBytesToReadFromFifo]), 0, uiNumBytes - uiNumBytesToReadFromFifo); } } else { for (UInt ui = 0; ui < uiNumBytes; ui++) { UInt uiByte; read(8, uiByte); buf.push_back(uiByte); } } if (uiNumBits&0x7) { UInt uiByte = 0; read(uiNumBits&0x7, uiByte); uiByte <<= 8-(uiNumBits&0x7); buf.push_back(uiByte); } return pResult; } UInt TComInputBitstream::readByteAlignment() { UInt code = 0; read( 1, code ); assert(code == 1); UInt numBits = getNumBitsUntilByteAligned(); if(numBits) { assert(numBits <= getNumBitsLeft()); read( numBits, code ); assert(code == 0); } return numBits+1; } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComBitStream.h000066400000000000000000000207041442026013100211030ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComBitStream.h \brief class for handling bitstream (header) */ #ifndef __TCOMBITSTREAM__ #define __TCOMBITSTREAM__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include #include "CommonDef.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// pure virtual class for basic bit handling class TComBitIf { public: virtual Void writeAlignOne () {}; virtual Void writeAlignZero () {}; virtual Void write ( UInt uiBits, UInt uiNumberOfBits ) = 0; virtual Void resetBits () = 0; virtual UInt getNumberOfWrittenBits() const = 0; virtual Int getNumBitsUntilByteAligned() const = 0; virtual ~TComBitIf() {} }; /** * Model of a writable bitstream that accumulates bits to produce a * bytestream. */ class TComOutputBitstream : public TComBitIf { /** * FIFO for storage of bytes. Use: * - fifo.push_back(x) to append words * - fifo.clear() to empty the FIFO * - &fifo.front() to get a pointer to the data array. * NB, this pointer is only valid until the next push_back()/clear() */ std::vector m_fifo; UInt m_num_held_bits; /// number of bits not flushed to bytestream. UChar m_held_bits; /// the bits held and not flushed to bytestream. /// this value is always msb-aligned, bigendian. public: // create / destroy TComOutputBitstream(); ~TComOutputBitstream(); // interface for encoding /** * append uiNumberOfBits least significant bits of uiBits to * the current bitstream */ Void write ( UInt uiBits, UInt uiNumberOfBits ); /** insert one bits until the bitstream is byte-aligned */ Void writeAlignOne (); /** insert zero bits until the bitstream is byte-aligned */ Void writeAlignZero (); /** this function should never be called */ Void resetBits() { assert(0); } // utility functions /** * Return a pointer to the start of the byte-stream buffer. * Pointer is valid until the next write/flush/reset call. * NB, data is arranged such that subsequent bytes in the * bytestream are stored in ascending addresses. */ UChar* getByteStream() const; /** * Return the number of valid bytes available from getByteStream() */ UInt getByteStreamLength(); /** * Reset all internal state. */ Void clear(); /** * returns the number of bits that need to be written to * achieve byte alignment. */ Int getNumBitsUntilByteAligned() const { return (8 - m_num_held_bits) & 0x7; } /** * Return the number of bits that have been written since the last clear() */ UInt getNumberOfWrittenBits() const { return UInt(m_fifo.size()) * 8 + m_num_held_bits; } Void insertAt(const TComOutputBitstream& src, UInt pos); /** * Return a reference to the internal fifo */ std::vector& getFIFO() { return m_fifo; } UChar getHeldBits () { return m_held_bits; } //TComOutputBitstream& operator= (const TComOutputBitstream& src); /** Return a reference to the internal fifo */ const std::vector& getFIFO() const { return m_fifo; } Void addSubstream ( TComOutputBitstream* pcSubstream ); Void writeByteAlignment(); //! returns the number of start code emulations contained in the current buffer Int countStartCodeEmulations(); }; /** * Model of an input bitstream that extracts bits from a predefined * bytestream. */ class TComInputBitstream { protected: std::vector m_fifo; /// FIFO for storage of complete bytes std::vector m_emulationPreventionByteLocation; UInt m_fifo_idx; /// Read index into m_fifo UInt m_num_held_bits; UChar m_held_bits; UInt m_numBitsRead; public: /** * Create a new bitstream reader object that reads from buf. */ TComInputBitstream(); virtual ~TComInputBitstream() { } TComInputBitstream(const TComInputBitstream &src); Void resetToStart(); // interface for decoding Void pseudoRead ( UInt uiNumberOfBits, UInt& ruiBits ); Void read ( UInt uiNumberOfBits, UInt& ruiBits ); Void readByte ( UInt &ruiBits ) { assert(m_fifo_idx < m_fifo.size()); ruiBits = m_fifo[m_fifo_idx++]; } Void peekPreviousByte( UInt &byte ) { assert(m_fifo_idx > 0); byte = m_fifo[m_fifo_idx - 1]; } UInt readOutTrailingBits (); UChar getHeldBits () { return m_held_bits; } TComOutputBitstream& operator= (const TComOutputBitstream& src); UInt getByteLocation ( ) { return m_fifo_idx ; } // Peek at bits in word-storage. Used in determining if we have completed reading of current bitstream and therefore slice in LCEC. UInt peekBits (UInt uiBits) { UInt tmp; pseudoRead(uiBits, tmp); return tmp; } // utility functions UInt read(UInt numberOfBits) { UInt tmp; read(numberOfBits, tmp); return tmp; } UInt readByte() { UInt tmp; readByte( tmp ); return tmp; } UInt getNumBitsUntilByteAligned() { return m_num_held_bits & (0x7); } UInt getNumBitsLeft() { return 8*((UInt)m_fifo.size() - m_fifo_idx) + m_num_held_bits; } TComInputBitstream *extractSubstream( UInt uiNumBits ); // Read the nominated number of bits, and return as a bitstream. UInt getNumBitsRead() { return m_numBitsRead; } UInt readByteAlignment(); Void pushEmulationPreventionByteLocation ( UInt pos ) { m_emulationPreventionByteLocation.push_back( pos ); } UInt numEmulationPreventionBytesRead () { return (UInt) m_emulationPreventionByteLocation.size(); } const std::vector &getEmulationPreventionByteLocation () const { return m_emulationPreventionByteLocation; } UInt getEmulationPreventionByteLocation ( UInt idx ) { return m_emulationPreventionByteLocation[ idx ]; } Void clearEmulationPreventionByteLocation() { m_emulationPreventionByteLocation.clear(); } Void setEmulationPreventionByteLocation ( const std::vector &vec ) { m_emulationPreventionByteLocation = vec; } const std::vector &getFifo() const { return m_fifo; } std::vector &getFifo() { return m_fifo; } }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComCABACTables.cpp000066400000000000000000000074231442026013100214730ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComCABACTables.cpp * \brief static class for CABAC tables */ #include "TComCABACTables.h" //! \ingroup TLibCommon //! \{ const UChar TComCABACTables::sm_aucLPSTable[1 << CONTEXT_STATE_BITS][4] = { { 128, 176, 208, 240}, { 128, 167, 197, 227}, { 128, 158, 187, 216}, { 123, 150, 178, 205}, { 116, 142, 169, 195}, { 111, 135, 160, 185}, { 105, 128, 152, 175}, { 100, 122, 144, 166}, { 95, 116, 137, 158}, { 90, 110, 130, 150}, { 85, 104, 123, 142}, { 81, 99, 117, 135}, { 77, 94, 111, 128}, { 73, 89, 105, 122}, { 69, 85, 100, 116}, { 66, 80, 95, 110}, { 62, 76, 90, 104}, { 59, 72, 86, 99}, { 56, 69, 81, 94}, { 53, 65, 77, 89}, { 51, 62, 73, 85}, { 48, 59, 69, 80}, { 46, 56, 66, 76}, { 43, 53, 63, 72}, { 41, 50, 59, 69}, { 39, 48, 56, 65}, { 37, 45, 54, 62}, { 35, 43, 51, 59}, { 33, 41, 48, 56}, { 32, 39, 46, 53}, { 30, 37, 43, 50}, { 29, 35, 41, 48}, { 27, 33, 39, 45}, { 26, 31, 37, 43}, { 24, 30, 35, 41}, { 23, 28, 33, 39}, { 22, 27, 32, 37}, { 21, 26, 30, 35}, { 20, 24, 29, 33}, { 19, 23, 27, 31}, { 18, 22, 26, 30}, { 17, 21, 25, 28}, { 16, 20, 23, 27}, { 15, 19, 22, 25}, { 14, 18, 21, 24}, { 14, 17, 20, 23}, { 13, 16, 19, 22}, { 12, 15, 18, 21}, { 12, 14, 17, 20}, { 11, 14, 16, 19}, { 11, 13, 15, 18}, { 10, 12, 15, 17}, { 10, 12, 14, 16}, { 9, 11, 13, 15}, { 9, 11, 12, 14}, { 8, 10, 12, 14}, { 8, 9, 11, 13}, { 7, 9, 11, 12}, { 7, 9, 10, 12}, { 7, 8, 10, 11}, { 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2} }; const UChar TComCABACTables::sm_aucRenormTable[32] = { 6, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //! \} HM-HM-18.0/source/Lib/TLibCommon/TComCABACTables.h000066400000000000000000000043521442026013100211360ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComCABACTables.h \brief static class for CABAC tables */ #ifndef __TCOMCABACTABLES__ #define __TCOMCABACTABLES__ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComRom.h" //! \ingroup TLibCommon //! \{ /** * \brief static class for CABAC tables */ class TComCABACTables { public: const static UChar sm_aucLPSTable[1 << CONTEXT_STATE_BITS][4]; const static UChar sm_aucRenormTable[32]; }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComChromaFormat.cpp000066400000000000000000000134111442026013100221230ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "TComChromaFormat.h" #include "TComPic.h" #include "TComDataCU.h" #include "TComTrQuant.h" #include "TComTU.h" //---------------------------------------------------------------------------------------------------------------------- InputColourSpaceConversion stringToInputColourSpaceConvert(const std::string &value, const Bool bIsForward) { if (value.empty() || value=="UNCHANGED") { return IPCOLOURSPACE_UNCHANGED; } if (bIsForward) { if (value=="YCbCrtoYYY") { return IPCOLOURSPACE_YCbCrtoYYY; } if (value=="YCbCrtoYCrCb") { return IPCOLOURSPACE_YCbCrtoYCrCb; } if (value=="RGBtoGBR") { return IPCOLOURSPACE_RGBtoGBR; } } else { if (value=="YCrCbtoYCbCr") { return IPCOLOURSPACE_YCbCrtoYCrCb; } if (value=="GBRtoRGB") { return IPCOLOURSPACE_RGBtoGBR; } } return NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS; } std::string getListOfColourSpaceConverts(const Bool bIsForward) { if (bIsForward) { return "UNCHANGED, YCbCrtoYCrCb, YCbCrtoYYY or RGBtoGBR"; } else { return "UNCHANGED, YCrCbtoYCbCr or GBRtoRGB"; } } //---------------------------------------------------------------------------------------------------------------------- Void getTUEntropyCodingParameters( TUEntropyCodingParameters &result, TComTU &rTu, const ComponentID component) { //------------------------------------------------ //set the local parameters TComDataCU *const pcCU = rTu.getCU(); const TComRectangle & area = rTu.getRect(component); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(component); const UInt log2BlockWidth = g_aucConvertToBit[area.width] + 2; const UInt log2BlockHeight = g_aucConvertToBit[area.height] + 2; const ChannelType channelType = toChannelType(component); result.scanType = COEFF_SCAN_TYPE(pcCU->getCoefScanIdx(uiAbsPartIdx, area.width, area.height, component)); //------------------------------------------------ //set the group layout result.widthInGroups = area.width >> MLS_CG_LOG2_WIDTH; result.heightInGroups = area.height >> MLS_CG_LOG2_HEIGHT; //------------------------------------------------ //set the scan orders const UInt log2WidthInGroups = g_aucConvertToBit[result.widthInGroups * 4]; const UInt log2HeightInGroups = g_aucConvertToBit[result.heightInGroups * 4]; result.scan = g_scanOrder[ SCAN_GROUPED_4x4 ][ result.scanType ][ log2BlockWidth ][ log2BlockHeight ]; result.scanCG = g_scanOrder[ SCAN_UNGROUPED ][ result.scanType ][ log2WidthInGroups ][ log2HeightInGroups ]; //------------------------------------------------ //set the significance map context selection parameters if (pcCU->getSlice()->getSPS()->getSpsRangeExtension().getTransformSkipContextEnabledFlag() && (pcCU->getCUTransquantBypass(uiAbsPartIdx) || (pcCU->getTransformSkip(uiAbsPartIdx, component) != 0))) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_SINGLE]; } else { if ((area.width == 4) && (area.height == 4)) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_4x4]; } else if ((area.width == 8) && (area.height == 8)) { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_8x8]; if (result.scanType != SCAN_DIAG) { result.firstSignificanceMapContext += nonDiagonalScan8x8ContextOffset[channelType]; } } else { result.firstSignificanceMapContext = significanceMapContextSetStart[channelType][CONTEXT_TYPE_NxN]; } } //------------------------------------------------ } //---------------------------------------------------------------------------------------------------------------------- HM-HM-18.0/source/Lib/TLibCommon/TComChromaFormat.h000066400000000000000000000335661442026013100216050ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __TCOMCHROMAFORMAT__ #define __TCOMCHROMAFORMAT__ #include "CommonDef.h" #include "TComRectangle.h" #include "ContextTables.h" #include "TComRom.h" #include #include #include #include "Debug.h" //====================================================================================================================== //Chroma format utility functions ===================================================================================== //====================================================================================================================== class TComDataCU; static inline ChannelType toChannelType (const ComponentID id) { return (id==COMPONENT_Y)? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA; } static inline Bool isLuma (const ComponentID id) { return (id==COMPONENT_Y); } static inline Bool isLuma (const ChannelType id) { return (id==CHANNEL_TYPE_LUMA); } static inline Bool isChroma (const ComponentID id) { return (id!=COMPONENT_Y); } static inline Bool isChroma (const ChannelType id) { return (id!=CHANNEL_TYPE_LUMA); } static inline UInt getChannelTypeScaleX (const ChannelType id, const ChromaFormat fmt) { return (isLuma(id) || (fmt==CHROMA_444)) ? 0 : 1; } static inline UInt getChannelTypeScaleY (const ChannelType id, const ChromaFormat fmt) { return (isLuma(id) || (fmt!=CHROMA_420)) ? 0 : 1; } static inline UInt getComponentScaleX (const ComponentID id, const ChromaFormat fmt) { return getChannelTypeScaleX(toChannelType(id), fmt); } static inline UInt getComponentScaleY (const ComponentID id, const ChromaFormat fmt) { return getChannelTypeScaleY(toChannelType(id), fmt); } static inline UInt getNumberValidChannelTypes(const ChromaFormat fmt) { return (fmt==CHROMA_400) ? 1 : MAX_NUM_CHANNEL_TYPE; } static inline UInt getNumberValidComponents (const ChromaFormat fmt) { return (fmt==CHROMA_400) ? 1 : MAX_NUM_COMPONENT; } static inline Bool isChromaEnabled (const ChromaFormat fmt) { return fmt!=CHROMA_400; } static inline ComponentID getFirstComponentOfChannel(const ChannelType id) { return (isLuma(id) ? COMPONENT_Y : COMPONENT_Cb); } InputColourSpaceConversion stringToInputColourSpaceConvert(const std::string &value, const Bool bIsForward); std::string getListOfColourSpaceConverts(const Bool bIsForward); //------------------------------------------------ static inline UInt getTotalSamples(const UInt width, const UInt height, const ChromaFormat format) { const UInt samplesPerChannel = width * height; switch (format) { case CHROMA_400: return samplesPerChannel; break; case CHROMA_420: return (samplesPerChannel * 3) >> 1; break; case CHROMA_422: return samplesPerChannel * 2; break; case CHROMA_444: return samplesPerChannel * 3; break; default: std::cerr << "ERROR: Unrecognised chroma format in getTotalSamples()" << std::endl; exit(1); break; } return MAX_UINT; } //------------------------------------------------ static inline UInt getTotalBits(const UInt width, const UInt height, const ChromaFormat format, const Int bitDepths[MAX_NUM_CHANNEL_TYPE]) { const UInt samplesPerChannel = width * height; switch (format) { case CHROMA_400: return samplesPerChannel * bitDepths[CHANNEL_TYPE_LUMA]; break; case CHROMA_420: return (samplesPerChannel * (bitDepths[CHANNEL_TYPE_LUMA]*2 + bitDepths[CHANNEL_TYPE_CHROMA]) ) >> 1; break; case CHROMA_422: return samplesPerChannel * (bitDepths[CHANNEL_TYPE_LUMA] + bitDepths[CHANNEL_TYPE_CHROMA]); break; case CHROMA_444: return samplesPerChannel * (bitDepths[CHANNEL_TYPE_LUMA] + 2*bitDepths[CHANNEL_TYPE_CHROMA]); break; default: std::cerr << "ERROR: Unrecognised chroma format in getTotalSamples()" << std::endl; exit(1); break; } return MAX_UINT; } //------------------------------------------------ // In HM, a CU only has one chroma intra prediction direction, that corresponds to the top left luma intra prediction // even if the NxN PU split occurs when 4 sub-TUs exist for chroma. // Use this function to allow NxN PU splitting for chroma. static inline Bool enable4ChromaPUsInIntraNxNCU(const ChromaFormat chFmt) { return (chFmt == CHROMA_444); } //------------------------------------------------ //returns the part index of the luma region that is co-located with the specified chroma region static inline UInt getChromasCorrespondingPULumaIdx(const UInt lumaZOrderIdxInCtu, const ChromaFormat chFmt, const Int partsPerMinCU // 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())) ) { return enable4ChromaPUsInIntraNxNCU(chFmt) ? lumaZOrderIdxInCtu : lumaZOrderIdxInCtu & (~(partsPerMinCU-1)); } //------------------------------------------------ // If chroma format is 4:2:2 and a chroma-square-sub-tu is possible for the smallest TU, then increase the depth by 1 to allow for more parts. static inline UInt getMaxCUDepthOffset(const ChromaFormat chFmt, const UInt quadtreeTULog2MinSize) { return (chFmt==CHROMA_422 && quadtreeTULog2MinSize>2) ? 1 : 0; } //====================================================================================================================== //Intra prediction ==================================================================================================== //====================================================================================================================== static inline Bool filterIntraReferenceSamples (const ChannelType chType, const ChromaFormat chFmt, const Bool intraReferenceSmoothingDisabled) { return (!intraReferenceSmoothingDisabled) && (isLuma(chType) || (chFmt == CHROMA_444)); } //====================================================================================================================== //Transform and Quantisation ========================================================================================== //====================================================================================================================== static inline Bool TUCompRectHasAssociatedTransformSkipFlag(const TComRectangle &rectSamples, const UInt transformSkipLog2MaxSize) { return (rectSamples.width <= (1<> 2)); result_offsetY = (isChroma(component)) ? 0 : ((convertedHeight * 3) + ((convertedHeight + 1) >> 2)); result_shiftX = (isChroma(component)) ? convertedWidth : ((convertedWidth + 3) >> 2); result_shiftY = (isChroma(component)) ? convertedHeight : ((convertedHeight + 3) >> 2); } //------------------------------------------------ //Function for significance map context index offset selection static inline UInt getSignificanceMapContextOffset (const ComponentID component) { return significanceMapContextStartTable[toChannelType(component)]; } //------------------------------------------------ // Function for greater-than-one map/greater-than-two map context set selection static inline UInt getContextSetIndex (const ComponentID component, const UInt subsetIndex, const Bool foundACoefficientGreaterThan1) { const UInt notFirstSubsetOffset = (isLuma(component) && (subsetIndex > 0)) ? 2 : 0; const UInt foundAGreaterThan1Offset = foundACoefficientGreaterThan1 ? 1 : 0; return contextSetStartTable[toChannelType(component)] + notFirstSubsetOffset + foundAGreaterThan1Offset; } //------------------------------------------------ //Function for CBF context index offset static inline UInt getCBFContextOffset (const ComponentID component) { return CBFContextStartTable[toChannelType(component)]; } //====================================================================================================================== //Entropy coding parameters ============================================================================================ //====================================================================================================================== Void getTUEntropyCodingParameters( TUEntropyCodingParameters &result, class TComTU &rTu, const ComponentID component); //====================================================================================================================== //End ================================================================================================================= //====================================================================================================================== #endif HM-HM-18.0/source/Lib/TLibCommon/TComCodingStatistics.h000066400000000000000000000417161442026013100224750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __TCOMCODINGSTATISTICS__ #define __TCOMCODINGSTATISTICS__ #include "CommonDef.h" #include #include #include #include #include "TComChromaFormat.h" static const Int64 TCOMCODINGSTATISTICS_ENTROPYSCALE=32768; enum TComCodingStatisticsType { STATS__NAL_UNIT_TOTAL_BODY,// This is a special case and is not included in the total sums. STATS__NAL_UNIT_PACKING, STATS__EMULATION_PREVENTION_3_BYTES, STATS__NAL_UNIT_HEADER_BITS, STATS__CABAC_INITIALISATION, STATS__CABAC_BITS__TQ_BYPASS_FLAG, STATS__CABAC_BITS__SKIP_FLAG, STATS__CABAC_BITS__MERGE_FLAG, STATS__CABAC_BITS__MERGE_INDEX, STATS__CABAC_BITS__MVP_IDX, STATS__CABAC_BITS__SPLIT_FLAG, STATS__CABAC_BITS__PART_SIZE, STATS__CABAC_BITS__PRED_MODE, STATS__CABAC_BITS__INTRA_DIR_ANG, STATS__CABAC_BITS__INTER_DIR, STATS__CABAC_BITS__REF_FRM_IDX, STATS__CABAC_BITS__MVD, STATS__CABAC_BITS__MVD_EP, STATS__CABAC_BITS__TRANSFORM_SUBDIV_FLAG, STATS__CABAC_BITS__QT_ROOT_CBF, STATS__CABAC_BITS__DELTA_QP_EP, STATS__CABAC_BITS__CHROMA_QP_ADJUSTMENT, STATS__CABAC_BITS__QT_CBF, STATS__CABAC_BITS__CROSS_COMPONENT_PREDICTION, STATS__CABAC_BITS__TRANSFORM_SKIP_FLAGS, STATS__CABAC_BITS__LAST_SIG_X_Y, STATS__CABAC_BITS__SIG_COEFF_GROUP_FLAG, STATS__CABAC_BITS__SIG_COEFF_MAP_FLAG, STATS__CABAC_BITS__GT1_FLAG, STATS__CABAC_BITS__GT2_FLAG, STATS__CABAC_BITS__SIGN_BIT, STATS__CABAC_BITS__ESCAPE_BITS, STATS__CABAC_BITS__SAO, STATS__CABAC_TRM_BITS, STATS__CABAC_FIXED_BITS, STATS__CABAC_PCM_ALIGN_BITS, STATS__CABAC_PCM_CODE_BITS, STATS__BYTE_ALIGNMENT_BITS, STATS__TRAILING_BITS, STATS__EXPLICIT_RDPCM_BITS, STATS__CABAC_EP_BIT_ALIGNMENT, STATS__CABAC_BITS__ALIGNED_SIGN_BIT, STATS__CABAC_BITS__ALIGNED_ESCAPE_BITS, STATS__NUM_STATS }; static inline const TChar* getName(TComCodingStatisticsType name) { static const TChar *statNames[]= { "NAL_UNIT_TOTAL_BODY", // This is a special case and is not included in the total sums. "NAL_UNIT_PACKING", "EMULATION_PREVENTION_3_BYTES", "NAL_UNIT_HEADER_BITS", "CABAC_INITIALISATION-and-rounding", "CABAC_BITS__TQ_BYPASS_FLAG", "CABAC_BITS__SKIP_FLAG", "CABAC_BITS__MERGE_FLAG", "CABAC_BITS__MERGE_INDEX", "CABAC_BITS__MVP_IDX", "CABAC_BITS__SPLIT_FLAG", "CABAC_BITS__PART_SIZE", "CABAC_BITS__PRED_MODE", "CABAC_BITS__INTRA_DIR_ANG", "CABAC_BITS__INTER_DIR", "CABAC_BITS__REF_FRM_IDX", "CABAC_BITS__MVD", "CABAC_BITS__MVD_EP", "CABAC_BITS__TRANSFORM_SUBDIV_FLAG", "CABAC_BITS__QT_ROOT_CBF", "CABAC_BITS__DELTA_QP_EP", "CABAC_BITS__CHROMA_QP_ADJUSTMENT", "CABAC_BITS__QT_CBF", "CABAC_BITS__CROSS_COMPONENT_PREDICTION", "CABAC_BITS__TRANSFORM_SKIP_FLAGS", "CABAC_BITS__LAST_SIG_X_Y", "CABAC_BITS__SIG_COEFF_GROUP_FLAG", "CABAC_BITS__SIG_COEFF_MAP_FLAG", "CABAC_BITS__GT1_FLAG", "CABAC_BITS__GT2_FLAG", "CABAC_BITS__SIGN_BIT", "CABAC_BITS__ESCAPE_BITS", "CABAC_BITS__SAO", "CABAC_TRM_BITS", "CABAC_FIXED_BITS", "CABAC_PCM_ALIGN_BITS", "CABAC_PCM_CODE_BITS", "BYTE_ALIGNMENT_BITS", "TRAILING_BITS", "EXPLICIT_RDPCM_BITS", "CABAC_EP_BIT_ALIGNMENT", "CABAC_BITS__ALIGNED_SIGN_BIT", "CABAC_BITS__ALIGNED_ESCAPE_BITS" }; assert(STATS__NUM_STATS == sizeof(statNames)/sizeof(TChar *) && name < STATS__NUM_STATS); return statNames[name]; } static inline Bool isAlignedBins(TComCodingStatisticsType statT) { return statT==STATS__CABAC_BITS__ALIGNED_SIGN_BIT || statT==STATS__CABAC_BITS__ALIGNED_ESCAPE_BITS; } static const UInt CODING_STATS_NUM_WIDTHS=7; static const UInt CODING_STATS_NUM_SUBCLASSES=CODING_STATS_NUM_WIDTHS*(1+MAX_NUM_COMPONENT+MAX_NUM_CHANNEL_TYPE); class TComCodingStatisticsClassType { public: TComCodingStatisticsClassType(const TComCodingStatisticsType t) : type(t), subClass(0) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const UInt log2w ) : type(t), subClass(log2w) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const Int log2w ) : type(t), subClass(log2w) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const ComponentID cid ) : type(t), subClass((cid+1)*CODING_STATS_NUM_WIDTHS) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const ChannelType chid ) : type(t), subClass((chid+MAX_NUM_COMPONENT+1)*CODING_STATS_NUM_WIDTHS) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const UInt log2w, const ComponentID cid ) : type(t), subClass((cid+1)*CODING_STATS_NUM_WIDTHS + log2w) { } TComCodingStatisticsClassType(const TComCodingStatisticsType t, const UInt log2w, const ChannelType chid ) : type(t), subClass((chid+MAX_NUM_COMPONENT+1)*CODING_STATS_NUM_WIDTHS + log2w) { } static UInt GetSubClassWidth(const UInt subClass) { return subClass%CODING_STATS_NUM_WIDTHS; } static const TChar *GetSubClassString(const UInt subClass) { assert (subClass mappings_ep; friend class TComCodingStatistics; }; private: TComCodingStatisticsData data; TComCodingStatistics() : data() { } static Void OutputLine(const TChar *pName, const TChar sep, UInt width, const TChar *pSubClassStr, const SStat &sCABAC, const SStat &sEP) { if (width==0) { OutputLine(pName, sep, "-", pSubClassStr, sCABAC, sEP); } else { printf("%c%-45s%c %6d %6s %12lld %12lld %12lld %12lld %12lld %12lld %12lld (%12lld)%c\n", sep=='~'?'[':' ', pName, sep, 1<::iterator it=data.mappings_ep.begin(); it!=data.mappings_ep.end(); it++) { SStat s=it->second; cavlcTotalBits+=s; OutputLine(it->first.c_str(), ':', "-", "-", s); } OutputDashedLine(""); OutputLine("CAVLC Header Sub-total", '~', "~~ST~~", "~~ST~~", cavlcTotalBits); // Now output the breakdowns OutputDashedLine("CABAC Break down by size"); for(UInt s=0; s> chromaShift; m_crossComponentPredictionAlpha[compID] = (SChar* )xMalloc(SChar, uiNumPartition); m_puhTransformSkip[compID] = (UChar* )xMalloc(UChar, uiNumPartition); m_explicitRdpcmMode[compID] = (UChar* )xMalloc(UChar, uiNumPartition); m_puhCbf[compID] = (UChar* )xMalloc(UChar, uiNumPartition); m_pcTrCoeff[compID] = (TCoeff*)xMalloc(TCoeff, totalSize); memset( m_pcTrCoeff[compID], 0, (totalSize * sizeof( TCoeff )) ); #if ADAPTIVE_QP_SELECTION if( pParentARLBuffer != 0 ) { m_pcArlCoeff[compID] = pParentARLBuffer; m_ArlCoeffIsAliasedAllocation = true; pParentARLBuffer += totalSize; } else { m_pcArlCoeff[compID] = (TCoeff*)xMalloc(TCoeff, totalSize); m_ArlCoeffIsAliasedAllocation = false; } #endif m_pcIPCMSample[compID] = (Pel* )xMalloc(Pel , totalSize); } m_pbIPCMFlag = (Bool* )xMalloc(Bool, uiNumPartition); for(UInt i=0; igetSlice() != NULL && m_pcPic->getPicSym()->getTileIdxMap( pCU->getCtuRsAddr() ) == m_pcPic->getPicSym()->getTileIdxMap(getCtuRsAddr()); } Bool TComDataCU::CUIsFromSameSliceAndTile ( const TComDataCU *pCU /* Can be NULL */) const { return pCU!=NULL && pCU->getSlice() != NULL && pCU->getSlice()->getSliceCurStartCtuTsAddr() == getSlice()->getSliceCurStartCtuTsAddr() && m_pcPic->getPicSym()->getTileIdxMap( pCU->getCtuRsAddr() ) == m_pcPic->getPicSym()->getTileIdxMap(getCtuRsAddr()) ; } Bool TComDataCU::CUIsFromSameSliceTileAndWavefrontRow( const TComDataCU *pCU /* Can be NULL */) const { return CUIsFromSameSliceAndTile(pCU) && (!getSlice()->getPPS()->getEntropyCodingSyncEnabledFlag() || getPic()->getCtu(getCtuRsAddr())->getCUPelY() == getPic()->getCtu(pCU->getCtuRsAddr())->getCUPelY()); } Bool TComDataCU::isLastSubCUOfCtu(const UInt absPartIdx) const { const TComSPS &sps=*(getSlice()->getSPS()); const UInt picWidth = sps.getPicWidthInLumaSamples(); const UInt picHeight = sps.getPicHeightInLumaSamples(); const UInt granularityWidth = sps.getMaxCUWidth(); const UInt cuPosX = getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[absPartIdx] ]; const UInt cuPosY = getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[absPartIdx] ]; return (((cuPosX+getWidth( absPartIdx))%granularityWidth==0||(cuPosX+getWidth( absPartIdx)==picWidth )) && ((cuPosY+getHeight(absPartIdx))%granularityWidth==0||(cuPosY+getHeight(absPartIdx)==picHeight))); } // ==================================================================================================================== // Public member functions // ==================================================================================================================== // -------------------------------------------------------------------------------------------------------------------- // Initialization // -------------------------------------------------------------------------------------------------------------------- /** Initialize top-level CU: create internal buffers and set initial values before encoding the CTU. \param pcPic picture (TComPic) class pointer \param ctuRsAddr CTU address in raster scan order */ Void TComDataCU::initCtu( TComPic* pcPic, UInt ctuRsAddr ) { const UInt maxCUWidth = pcPic->getPicSym()->getSPS().getMaxCUWidth(); const UInt maxCUHeight= pcPic->getPicSym()->getSPS().getMaxCUHeight(); m_pcPic = pcPic; m_pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx()); m_ctuRsAddr = ctuRsAddr; m_uiCUPelX = ( ctuRsAddr % pcPic->getFrameWidthInCtus() ) * maxCUWidth; m_uiCUPelY = ( ctuRsAddr / pcPic->getFrameWidthInCtus() ) * maxCUHeight; m_absZIdxInCtu = 0; m_dTotalCost = MAX_DOUBLE; m_uiTotalDistortion = 0; m_uiTotalBits = 0; m_uiTotalBins = 0; m_uiNumPartition = pcPic->getNumPartitionsInCtu(); memset( m_skipFlag , false, m_uiNumPartition * sizeof( *m_skipFlag ) ); memset( m_pePartSize , NUMBER_OF_PART_SIZES, m_uiNumPartition * sizeof( *m_pePartSize ) ); memset( m_pePredMode , NUMBER_OF_PREDICTION_MODES, m_uiNumPartition * sizeof( *m_pePredMode ) ); memset( m_CUTransquantBypass, false, m_uiNumPartition * sizeof( *m_CUTransquantBypass) ); memset( m_puhDepth , 0, m_uiNumPartition * sizeof( *m_puhDepth ) ); memset( m_puhTrIdx , 0, m_uiNumPartition * sizeof( *m_puhTrIdx ) ); memset( m_puhWidth , maxCUWidth, m_uiNumPartition * sizeof( *m_puhWidth ) ); memset( m_puhHeight , maxCUHeight, m_uiNumPartition * sizeof( *m_puhHeight ) ); for(UInt i=0; igetSliceQp(), m_uiNumPartition * sizeof( *m_phQP ) ); memset( m_ChromaQpAdj , 0, m_uiNumPartition * sizeof( *m_ChromaQpAdj ) ); for(UInt comp=0; compgetComponentScaleX(ComponentID(comp)) + m_pcPic->getComponentScaleY(ComponentID(comp)); memset( m_pcTrCoeff[comp], 0, sizeof(TCoeff)* numCoeffY>>componentShift ); #if ADAPTIVE_QP_SELECTION memset( m_pcArlCoeff[comp], 0, sizeof(TCoeff)* numCoeffY>>componentShift ); #endif } for(UInt i=0; igetFrameWidthInCtus(); if ( m_ctuRsAddr % frameWidthInCtus ) { m_pCtuLeft = pcPic->getCtu( m_ctuRsAddr - 1 ); } if ( m_ctuRsAddr / frameWidthInCtus ) { m_pCtuAbove = pcPic->getCtu( m_ctuRsAddr - frameWidthInCtus ); } if ( m_pCtuLeft && m_pCtuAbove ) { m_pCtuAboveLeft = pcPic->getCtu( m_ctuRsAddr - frameWidthInCtus - 1 ); } if ( m_pCtuAbove && ( (m_ctuRsAddr%frameWidthInCtus) < (frameWidthInCtus-1) ) ) { m_pCtuAboveRight = pcPic->getCtu( m_ctuRsAddr - frameWidthInCtus + 1 ); } } /** Initialize prediction data with enabling sub-CTU-level delta QP. * - set CU width and CU height according to depth * - set qp value according to input qp * - set last-coded qp value according to input last-coded qp * * \param uiDepth depth of the current CU * \param qp qp for the current CU * \param bTransquantBypass true for transquant bypass */ Void TComDataCU::initEstData( const UInt uiDepth, const Int qp, const Bool bTransquantBypass ) { m_dTotalCost = MAX_DOUBLE; m_uiTotalDistortion = 0; m_uiTotalBits = 0; m_uiTotalBins = 0; const UChar uhWidth = getSlice()->getSPS()->getMaxCUWidth() >> uiDepth; const UChar uhHeight = getSlice()->getSPS()->getMaxCUHeight() >> uiDepth; for (UInt ui = 0; ui < m_uiNumPartition; ui++) { for(UInt i=0; i> (getPic()->getComponentScaleX(component) + getPic()->getComponentScaleY(component)); memset( m_pcTrCoeff[comp], 0, numCoeff * sizeof( TCoeff ) ); #if ADAPTIVE_QP_SELECTION memset( m_pcArlCoeff[comp], 0, numCoeff * sizeof( TCoeff ) ); #endif memset( m_pcIPCMSample[comp], 0, numCoeff * sizeof( Pel) ); } } // initialize Sub partition Void TComDataCU::initSubCU( TComDataCU* pcCU, UInt uiPartUnitIdx, UInt uiDepth, Int qp ) { assert( uiPartUnitIdx<4 ); UInt uiPartOffset = ( pcCU->getTotalNumPart()>>2 )*uiPartUnitIdx; m_pcPic = pcCU->getPic(); m_pcSlice = pcCU->getSlice(); m_ctuRsAddr = pcCU->getCtuRsAddr(); m_absZIdxInCtu = pcCU->getZorderIdxInCtu() + uiPartOffset; const UChar uhWidth = getSlice()->getSPS()->getMaxCUWidth() >> uiDepth; const UChar uhHeight = getSlice()->getSPS()->getMaxCUHeight() >> uiDepth; m_uiCUPelX = pcCU->getCUPelX() + ( uhWidth )*( uiPartUnitIdx & 1 ); m_uiCUPelY = pcCU->getCUPelY() + ( uhHeight)*( uiPartUnitIdx >> 1 ); m_dTotalCost = MAX_DOUBLE; m_uiTotalDistortion = 0; m_uiTotalBits = 0; m_uiTotalBins = 0; m_uiNumPartition = pcCU->getTotalNumPart() >> 2; Int iSizeInUchar = sizeof( UChar ) * m_uiNumPartition; Int iSizeInBool = sizeof( Bool ) * m_uiNumPartition; Int sizeInChar = sizeof( SChar ) * m_uiNumPartition; memset( m_phQP, qp, sizeInChar ); memset( m_pbMergeFlag, 0, iSizeInBool ); memset( m_puhMergeIndex, 0, iSizeInUchar ); for (UInt ch=0; chgetComponentScaleX(ComponentID(ch)) + m_pcPic->getComponentScaleY(ComponentID(ch)); memset( m_pcTrCoeff[ch], 0, sizeof(TCoeff)*(numCoeffY>>componentShift) ); #if ADAPTIVE_QP_SELECTION memset( m_pcArlCoeff[ch], 0, sizeof(TCoeff)*(numCoeffY>>componentShift) ); #endif memset( m_pcIPCMSample[ch], 0, sizeof(Pel)* (numCoeffY>>componentShift) ); } for(UInt i=0; igetCtuLeft(); m_pCtuAbove = pcCU->getCtuAbove(); m_pCtuAboveLeft = pcCU->getCtuAboveLeft(); m_pCtuAboveRight = pcCU->getCtuAboveRight(); } Void TComDataCU::setOutsideCUPart( UInt uiAbsPartIdx, UInt uiDepth ) { const UInt uiNumPartition = m_uiNumPartition >> (uiDepth << 1); const UInt uiSizeInUchar = sizeof( UChar ) * uiNumPartition; const TComSPS &sps = *(getSlice()->getSPS()); const UChar uhWidth = sps.getMaxCUWidth() >> uiDepth; const UChar uhHeight = sps.getMaxCUHeight() >> uiDepth; memset( m_puhDepth + uiAbsPartIdx, uiDepth, uiSizeInUchar ); memset( m_puhWidth + uiAbsPartIdx, uhWidth, uiSizeInUchar ); memset( m_puhHeight + uiAbsPartIdx, uhHeight, uiSizeInUchar ); } // -------------------------------------------------------------------------------------------------------------------- // Copy // -------------------------------------------------------------------------------------------------------------------- Void TComDataCU::copySubCU( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiPart = uiAbsPartIdx; m_pcPic = pcCU->getPic(); m_pcSlice = pcCU->getSlice(); m_ctuRsAddr = pcCU->getCtuRsAddr(); m_absZIdxInCtu = uiAbsPartIdx; m_uiCUPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; m_uiCUPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ]; m_skipFlag=pcCU->getSkipFlag() + uiPart; m_phQP=pcCU->getQP() + uiPart; m_ChromaQpAdj = pcCU->getChromaQpAdj() + uiPart; m_pePartSize = pcCU->getPartitionSize() + uiPart; m_pePredMode=pcCU->getPredictionMode() + uiPart; m_CUTransquantBypass = pcCU->getCUTransquantBypass()+uiPart; m_pbMergeFlag = pcCU->getMergeFlag() + uiPart; m_puhMergeIndex = pcCU->getMergeIndex() + uiPart; for (UInt ch=0; chgetIntraDir(ChannelType(ch)) + uiPart; } m_puhInterDir = pcCU->getInterDir() + uiPart; m_puhTrIdx = pcCU->getTransformIdx() + uiPart; for(UInt comp=0; compgetCrossComponentPredictionAlpha(ComponentID(comp)) + uiPart; m_puhTransformSkip[comp] = pcCU->getTransformSkip(ComponentID(comp)) + uiPart; m_puhCbf[comp] = pcCU->getCbf(ComponentID(comp)) + uiPart; m_explicitRdpcmMode[comp] = pcCU->getExplicitRdpcmMode(ComponentID(comp)) + uiPart; } m_puhDepth=pcCU->getDepth() + uiPart; m_puhWidth=pcCU->getWidth() + uiPart; m_puhHeight=pcCU->getHeight() + uiPart; m_pbIPCMFlag = pcCU->getIPCMFlag() + uiPart; m_pCtuAboveLeft = pcCU->getCtuAboveLeft(); m_pCtuAboveRight = pcCU->getCtuAboveRight(); m_pCtuAbove = pcCU->getCtuAbove(); m_pCtuLeft = pcCU->getCtuLeft(); for(UInt i=0; igetMVPIdx(rpl) + uiPart; m_apiMVPNum[rpl]=pcCU->getMVPNum(rpl) + uiPart; } for(UInt i=0; igetCUMvField(rpl), uiPart ); } UInt uiMaxCuWidth=pcCU->getSlice()->getSPS()->getMaxCUWidth(); UInt uiMaxCuHeight=pcCU->getSlice()->getSPS()->getMaxCUHeight(); UInt uiCoffOffset = uiMaxCuWidth*uiMaxCuHeight*uiAbsPartIdx/pcCU->getPic()->getNumPartitionsInCtu(); for (UInt ch=0; chgetComponentScaleX(component) + m_pcPic->getComponentScaleY(component); const UInt offset = uiCoffOffset >> componentShift; m_pcTrCoeff[ch] = pcCU->getCoeff(component) + offset; #if ADAPTIVE_QP_SELECTION m_pcArlCoeff[ch] = pcCU->getArlCoeff(component) + offset; #endif m_pcIPCMSample[ch] = pcCU->getPCMSample(component) + offset; } } // Copy inter prediction info from the biggest CU Void TComDataCU::copyInterPredInfoFrom ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefPicList ) { m_pcPic = pcCU->getPic(); m_pcSlice = pcCU->getSlice(); m_ctuRsAddr = pcCU->getCtuRsAddr(); m_absZIdxInCtu = uiAbsPartIdx; Int iRastPartIdx = g_auiZscanToRaster[uiAbsPartIdx]; m_uiCUPelX = pcCU->getCUPelX() + m_pcPic->getMinCUWidth ()*( iRastPartIdx % m_pcPic->getNumPartInCtuWidth() ); m_uiCUPelY = pcCU->getCUPelY() + m_pcPic->getMinCUHeight()*( iRastPartIdx / m_pcPic->getNumPartInCtuWidth() ); m_pCtuAboveLeft = pcCU->getCtuAboveLeft(); m_pCtuAboveRight = pcCU->getCtuAboveRight(); m_pCtuAbove = pcCU->getCtuAbove(); m_pCtuLeft = pcCU->getCtuLeft(); m_skipFlag = pcCU->getSkipFlag () + uiAbsPartIdx; m_pePartSize = pcCU->getPartitionSize () + uiAbsPartIdx; m_pePredMode = pcCU->getPredictionMode() + uiAbsPartIdx; m_ChromaQpAdj = pcCU->getChromaQpAdj() + uiAbsPartIdx; m_CUTransquantBypass = pcCU->getCUTransquantBypass() + uiAbsPartIdx; m_puhInterDir = pcCU->getInterDir () + uiAbsPartIdx; m_puhDepth = pcCU->getDepth () + uiAbsPartIdx; m_puhWidth = pcCU->getWidth () + uiAbsPartIdx; m_puhHeight = pcCU->getHeight() + uiAbsPartIdx; m_pbMergeFlag = pcCU->getMergeFlag() + uiAbsPartIdx; m_puhMergeIndex = pcCU->getMergeIndex() + uiAbsPartIdx; m_apiMVPIdx[eRefPicList] = pcCU->getMVPIdx(eRefPicList) + uiAbsPartIdx; m_apiMVPNum[eRefPicList] = pcCU->getMVPNum(eRefPicList) + uiAbsPartIdx; m_acCUMvField[ eRefPicList ].linkToWithOffset( pcCU->getCUMvField(eRefPicList), uiAbsPartIdx ); } // Copy small CU to bigger CU. // One of quarter parts overwritten by predicted sub part. Void TComDataCU::copyPartFrom( TComDataCU* pcCU, UInt uiPartUnitIdx, UInt uiDepth ) { assert( uiPartUnitIdx<4 ); m_dTotalCost += pcCU->getTotalCost(); m_uiTotalDistortion += pcCU->getTotalDistortion(); m_uiTotalBits += pcCU->getTotalBits(); UInt uiOffset = pcCU->getTotalNumPart()*uiPartUnitIdx; const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); const UInt numValidChan=pcCU->getPic()->getChromaFormat()==CHROMA_400 ? 1:2; UInt uiNumPartition = pcCU->getTotalNumPart(); Int iSizeInUchar = sizeof( UChar ) * uiNumPartition; Int iSizeInBool = sizeof( Bool ) * uiNumPartition; Int sizeInChar = sizeof( SChar ) * uiNumPartition; memcpy( m_skipFlag + uiOffset, pcCU->getSkipFlag(), sizeof( *m_skipFlag ) * uiNumPartition ); memcpy( m_phQP + uiOffset, pcCU->getQP(), sizeInChar ); memcpy( m_pePartSize + uiOffset, pcCU->getPartitionSize(), sizeof( *m_pePartSize ) * uiNumPartition ); memcpy( m_pePredMode + uiOffset, pcCU->getPredictionMode(), sizeof( *m_pePredMode ) * uiNumPartition ); memcpy( m_ChromaQpAdj + uiOffset, pcCU->getChromaQpAdj(), sizeof( *m_ChromaQpAdj ) * uiNumPartition ); memcpy( m_CUTransquantBypass + uiOffset, pcCU->getCUTransquantBypass(), sizeof( *m_CUTransquantBypass ) * uiNumPartition ); memcpy( m_pbMergeFlag + uiOffset, pcCU->getMergeFlag(), iSizeInBool ); memcpy( m_puhMergeIndex + uiOffset, pcCU->getMergeIndex(), iSizeInUchar ); for (UInt ch=0; chgetIntraDir(ChannelType(ch)), iSizeInUchar ); } memcpy( m_puhInterDir + uiOffset, pcCU->getInterDir(), iSizeInUchar ); memcpy( m_puhTrIdx + uiOffset, pcCU->getTransformIdx(), iSizeInUchar ); for(UInt comp=0; compgetCrossComponentPredictionAlpha(ComponentID(comp)), iSizeInUchar ); memcpy( m_puhTransformSkip[comp] + uiOffset, pcCU->getTransformSkip(ComponentID(comp)) , iSizeInUchar ); memcpy( m_puhCbf[comp] + uiOffset, pcCU->getCbf(ComponentID(comp)) , iSizeInUchar ); memcpy( m_explicitRdpcmMode[comp] + uiOffset, pcCU->getExplicitRdpcmMode(ComponentID(comp)) , iSizeInUchar ); } memcpy( m_puhDepth + uiOffset, pcCU->getDepth(), iSizeInUchar ); memcpy( m_puhWidth + uiOffset, pcCU->getWidth(), iSizeInUchar ); memcpy( m_puhHeight + uiOffset, pcCU->getHeight(), iSizeInUchar ); memcpy( m_pbIPCMFlag + uiOffset, pcCU->getIPCMFlag(), iSizeInBool ); m_pCtuAboveLeft = pcCU->getCtuAboveLeft(); m_pCtuAboveRight = pcCU->getCtuAboveRight(); m_pCtuAbove = pcCU->getCtuAbove(); m_pCtuLeft = pcCU->getCtuLeft(); for(UInt i=0; igetMVPIdx(rpl), iSizeInUchar ); memcpy( m_apiMVPNum[rpl] + uiOffset, pcCU->getMVPNum(rpl), iSizeInUchar ); } for(UInt i=0; igetCUMvField( rpl ), pcCU->getTotalNumPart(), uiOffset ); } const UInt numCoeffY = (pcCU->getSlice()->getSPS()->getMaxCUWidth()*pcCU->getSlice()->getSPS()->getMaxCUHeight()) >> (uiDepth<<1); const UInt offsetY = uiPartUnitIdx*numCoeffY; for (UInt ch=0; chgetComponentScaleX(component) + m_pcPic->getComponentScaleY(component); const UInt offset = offsetY>>componentShift; memcpy( m_pcTrCoeff [ch] + offset, pcCU->getCoeff(component), sizeof(TCoeff)*(numCoeffY>>componentShift) ); #if ADAPTIVE_QP_SELECTION memcpy( m_pcArlCoeff[ch] + offset, pcCU->getArlCoeff(component), sizeof(TCoeff)*(numCoeffY>>componentShift) ); #endif memcpy( m_pcIPCMSample[ch] + offset, pcCU->getPCMSample(component), sizeof(Pel)*(numCoeffY>>componentShift) ); } m_uiTotalBins += pcCU->getTotalBins(); } // Copy current predicted part to a CU in picture. // It is used to predict for next part Void TComDataCU::copyToPic( UChar uhDepth ) { TComDataCU* pCtu = m_pcPic->getCtu( m_ctuRsAddr ); const UInt numValidComp=pCtu->getPic()->getNumberValidComponents(); const UInt numValidChan=pCtu->getPic()->getChromaFormat()==CHROMA_400 ? 1:2; pCtu->getTotalCost() = m_dTotalCost; pCtu->getTotalDistortion() = m_uiTotalDistortion; pCtu->getTotalBits() = m_uiTotalBits; Int iSizeInUchar = sizeof( UChar ) * m_uiNumPartition; Int iSizeInBool = sizeof( Bool ) * m_uiNumPartition; Int sizeInChar = sizeof( SChar ) * m_uiNumPartition; memcpy( pCtu->getSkipFlag() + m_absZIdxInCtu, m_skipFlag, sizeof( *m_skipFlag ) * m_uiNumPartition ); memcpy( pCtu->getQP() + m_absZIdxInCtu, m_phQP, sizeInChar ); memcpy( pCtu->getPartitionSize() + m_absZIdxInCtu, m_pePartSize, sizeof( *m_pePartSize ) * m_uiNumPartition ); memcpy( pCtu->getPredictionMode() + m_absZIdxInCtu, m_pePredMode, sizeof( *m_pePredMode ) * m_uiNumPartition ); memcpy( pCtu->getChromaQpAdj() + m_absZIdxInCtu, m_ChromaQpAdj, sizeof( *m_ChromaQpAdj ) * m_uiNumPartition ); memcpy( pCtu->getCUTransquantBypass()+ m_absZIdxInCtu, m_CUTransquantBypass, sizeof( *m_CUTransquantBypass ) * m_uiNumPartition ); memcpy( pCtu->getMergeFlag() + m_absZIdxInCtu, m_pbMergeFlag, iSizeInBool ); memcpy( pCtu->getMergeIndex() + m_absZIdxInCtu, m_puhMergeIndex, iSizeInUchar ); for (UInt ch=0; chgetIntraDir(ChannelType(ch)) + m_absZIdxInCtu, m_puhIntraDir[ch], iSizeInUchar); } memcpy( pCtu->getInterDir() + m_absZIdxInCtu, m_puhInterDir, iSizeInUchar ); memcpy( pCtu->getTransformIdx() + m_absZIdxInCtu, m_puhTrIdx, iSizeInUchar ); for(UInt comp=0; compgetCrossComponentPredictionAlpha(ComponentID(comp)) + m_absZIdxInCtu, m_crossComponentPredictionAlpha[comp], iSizeInUchar ); memcpy( pCtu->getTransformSkip(ComponentID(comp)) + m_absZIdxInCtu, m_puhTransformSkip[comp], iSizeInUchar ); memcpy( pCtu->getCbf(ComponentID(comp)) + m_absZIdxInCtu, m_puhCbf[comp], iSizeInUchar ); memcpy( pCtu->getExplicitRdpcmMode(ComponentID(comp)) + m_absZIdxInCtu, m_explicitRdpcmMode[comp], iSizeInUchar ); } memcpy( pCtu->getDepth() + m_absZIdxInCtu, m_puhDepth, iSizeInUchar ); memcpy( pCtu->getWidth() + m_absZIdxInCtu, m_puhWidth, iSizeInUchar ); memcpy( pCtu->getHeight() + m_absZIdxInCtu, m_puhHeight, iSizeInUchar ); for(UInt i=0; igetMVPIdx(rpl) + m_absZIdxInCtu, m_apiMVPIdx[rpl], iSizeInUchar ); memcpy( pCtu->getMVPNum(rpl) + m_absZIdxInCtu, m_apiMVPNum[rpl], iSizeInUchar ); } for(UInt i=0; igetCUMvField( rpl ), m_absZIdxInCtu ); } memcpy( pCtu->getIPCMFlag() + m_absZIdxInCtu, m_pbIPCMFlag, iSizeInBool ); const UInt numCoeffY = (pCtu->getSlice()->getSPS()->getMaxCUWidth()*pCtu->getSlice()->getSPS()->getMaxCUHeight())>>(uhDepth<<1); const UInt offsetY = m_absZIdxInCtu*m_pcPic->getMinCUWidth()*m_pcPic->getMinCUHeight(); for (UInt comp=0; compgetComponentScaleX(component) + m_pcPic->getComponentScaleY(component); memcpy( pCtu->getCoeff(component) + (offsetY>>componentShift), m_pcTrCoeff[component], sizeof(TCoeff)*(numCoeffY>>componentShift) ); #if ADAPTIVE_QP_SELECTION memcpy( pCtu->getArlCoeff(component) + (offsetY>>componentShift), m_pcArlCoeff[component], sizeof(TCoeff)*(numCoeffY>>componentShift) ); #endif memcpy( pCtu->getPCMSample(component) + (offsetY>>componentShift), m_pcIPCMSample[component], sizeof(Pel)*(numCoeffY>>componentShift) ); } pCtu->getTotalBins() = m_uiTotalBins; } // -------------------------------------------------------------------------------------------------------------------- // Other public functions // -------------------------------------------------------------------------------------------------------------------- const TComDataCU* TComDataCU::getPULeft( UInt& uiLPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction, Bool bEnforceTileRestriction ) const { UInt uiAbsPartIdx = g_auiZscanToRaster[uiCurrPartUnitIdx]; UInt uiAbsZorderCUIdx = g_auiZscanToRaster[m_absZIdxInCtu]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); if ( !RasterAddress::isZeroCol( uiAbsPartIdx, numPartInCtuWidth ) ) { uiLPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx - 1 ]; if ( RasterAddress::isEqualCol( uiAbsPartIdx, uiAbsZorderCUIdx, numPartInCtuWidth ) ) { return m_pcPic->getCtu( getCtuRsAddr() ); } else { uiLPartUnitIdx -= m_absZIdxInCtu; return this; } } uiLPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx + numPartInCtuWidth - 1 ]; if ( (bEnforceSliceRestriction && !CUIsFromSameSlice(m_pCtuLeft)) || (bEnforceTileRestriction && !CUIsFromSameTile(m_pCtuLeft)) ) { return NULL; } return m_pCtuLeft; } const TComDataCU* TComDataCU::getPUAbove( UInt& uiAPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction, Bool planarAtCtuBoundary, Bool bEnforceTileRestriction ) const { UInt uiAbsPartIdx = g_auiZscanToRaster[uiCurrPartUnitIdx]; UInt uiAbsZorderCUIdx = g_auiZscanToRaster[m_absZIdxInCtu]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); if ( !RasterAddress::isZeroRow( uiAbsPartIdx, numPartInCtuWidth ) ) { uiAPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx - numPartInCtuWidth ]; if ( RasterAddress::isEqualRow( uiAbsPartIdx, uiAbsZorderCUIdx, numPartInCtuWidth ) ) { return m_pcPic->getCtu( getCtuRsAddr() ); } else { uiAPartUnitIdx -= m_absZIdxInCtu; return this; } } if(planarAtCtuBoundary) { return NULL; } uiAPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx + m_pcPic->getNumPartitionsInCtu() - numPartInCtuWidth ]; if ( (bEnforceSliceRestriction && !CUIsFromSameSlice(m_pCtuAbove)) || (bEnforceTileRestriction && !CUIsFromSameTile(m_pCtuAbove)) ) { return NULL; } return m_pCtuAbove; } const TComDataCU* TComDataCU::getPUAboveLeft( UInt& uiALPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction ) const { UInt uiAbsPartIdx = g_auiZscanToRaster[uiCurrPartUnitIdx]; UInt uiAbsZorderCUIdx = g_auiZscanToRaster[m_absZIdxInCtu]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); if ( !RasterAddress::isZeroCol( uiAbsPartIdx, numPartInCtuWidth ) ) { if ( !RasterAddress::isZeroRow( uiAbsPartIdx, numPartInCtuWidth ) ) { uiALPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx - numPartInCtuWidth - 1 ]; if ( RasterAddress::isEqualRowOrCol( uiAbsPartIdx, uiAbsZorderCUIdx, numPartInCtuWidth ) ) { return m_pcPic->getCtu( getCtuRsAddr() ); } else { uiALPartUnitIdx -= m_absZIdxInCtu; return this; } } uiALPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx + getPic()->getNumPartitionsInCtu() - numPartInCtuWidth - 1 ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuAbove) ) { return NULL; } return m_pCtuAbove; } if ( !RasterAddress::isZeroRow( uiAbsPartIdx, numPartInCtuWidth ) ) { uiALPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdx - 1 ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuLeft) ) { return NULL; } return m_pCtuLeft; } uiALPartUnitIdx = g_auiRasterToZscan[ m_pcPic->getNumPartitionsInCtu() - 1 ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuAboveLeft) ) { return NULL; } return m_pCtuAboveLeft; } const TComDataCU* TComDataCU::getPUBelowLeft(UInt& uiBLPartUnitIdx, UInt uiCurrPartUnitIdx, UInt uiPartUnitOffset, Bool bEnforceSliceRestriction) const { UInt uiAbsPartIdxLB = g_auiZscanToRaster[uiCurrPartUnitIdx]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); UInt uiAbsZorderCUIdxLB = g_auiZscanToRaster[ m_absZIdxInCtu ] + ((m_puhHeight[0] / m_pcPic->getMinCUHeight()) - 1)*numPartInCtuWidth; if( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxLB] + (m_pcPic->getPicSym()->getMinCUHeight() * uiPartUnitOffset)) >= m_pcSlice->getSPS()->getPicHeightInLumaSamples()) { uiBLPartUnitIdx = MAX_UINT; return NULL; } if ( RasterAddress::lessThanRow( uiAbsPartIdxLB, m_pcPic->getNumPartInCtuHeight() - uiPartUnitOffset, numPartInCtuWidth ) ) { if ( !RasterAddress::isZeroCol( uiAbsPartIdxLB, numPartInCtuWidth ) ) { if ( uiCurrPartUnitIdx > g_auiRasterToZscan[ uiAbsPartIdxLB + uiPartUnitOffset * numPartInCtuWidth - 1 ] ) { uiBLPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdxLB + uiPartUnitOffset * numPartInCtuWidth - 1 ]; if ( RasterAddress::isEqualRowOrCol( uiAbsPartIdxLB, uiAbsZorderCUIdxLB, numPartInCtuWidth ) ) { return m_pcPic->getCtu( getCtuRsAddr() ); } else { uiBLPartUnitIdx -= m_absZIdxInCtu; return this; } } uiBLPartUnitIdx = MAX_UINT; return NULL; } uiBLPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdxLB + (1+uiPartUnitOffset) * numPartInCtuWidth - 1 ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuLeft) ) { return NULL; } return m_pCtuLeft; } uiBLPartUnitIdx = MAX_UINT; return NULL; } const TComDataCU* TComDataCU::getPUAboveRight(UInt& uiARPartUnitIdx, UInt uiCurrPartUnitIdx, UInt uiPartUnitOffset, Bool bEnforceSliceRestriction) const { UInt uiAbsPartIdxRT = g_auiZscanToRaster[uiCurrPartUnitIdx]; UInt uiAbsZorderCUIdx = g_auiZscanToRaster[ m_absZIdxInCtu ] + (m_puhWidth[0] / m_pcPic->getMinCUWidth()) - 1; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); if( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxRT] + (m_pcPic->getPicSym()->getMinCUHeight() * uiPartUnitOffset)) >= m_pcSlice->getSPS()->getPicWidthInLumaSamples() ) { uiARPartUnitIdx = MAX_UINT; return NULL; } if ( RasterAddress::lessThanCol( uiAbsPartIdxRT, numPartInCtuWidth - uiPartUnitOffset, numPartInCtuWidth ) ) { if ( !RasterAddress::isZeroRow( uiAbsPartIdxRT, numPartInCtuWidth ) ) { if ( uiCurrPartUnitIdx > g_auiRasterToZscan[ uiAbsPartIdxRT - numPartInCtuWidth + uiPartUnitOffset ] ) { uiARPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdxRT - numPartInCtuWidth + uiPartUnitOffset ]; if ( RasterAddress::isEqualRowOrCol( uiAbsPartIdxRT, uiAbsZorderCUIdx, numPartInCtuWidth ) ) { return m_pcPic->getCtu( getCtuRsAddr() ); } else { uiARPartUnitIdx -= m_absZIdxInCtu; return this; } } uiARPartUnitIdx = MAX_UINT; return NULL; } uiARPartUnitIdx = g_auiRasterToZscan[ uiAbsPartIdxRT + m_pcPic->getNumPartitionsInCtu() - numPartInCtuWidth + uiPartUnitOffset ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuAbove) ) { return NULL; } return m_pCtuAbove; } if ( !RasterAddress::isZeroRow( uiAbsPartIdxRT, numPartInCtuWidth ) ) { uiARPartUnitIdx = MAX_UINT; return NULL; } uiARPartUnitIdx = g_auiRasterToZscan[ m_pcPic->getNumPartitionsInCtu() - numPartInCtuWidth + uiPartUnitOffset-1 ]; if ( bEnforceSliceRestriction && !CUIsFromSameSliceAndTile(m_pCtuAboveRight) ) { return NULL; } return m_pCtuAboveRight; } /** Get left QpMinCu *\param uiLPartUnitIdx *\param uiCurrAbsIdxInCtu *\returns TComDataCU* point of TComDataCU of left QpMinCu */ const TComDataCU* TComDataCU::getQpMinCuLeft( UInt& uiLPartUnitIdx, UInt uiCurrAbsIdxInCtu ) const { const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); const UInt maxCUDepth = getSlice()->getSPS()->getMaxTotalCUDepth(); const UInt maxCuDQPDepth = getSlice()->getPPS()->getMaxCuDQPDepth(); const UInt doubleDepthDifference = ((maxCUDepth - maxCuDQPDepth)<<1); UInt absZorderQpMinCUIdx = (uiCurrAbsIdxInCtu>>doubleDepthDifference)<getCtu( getCtuRsAddr() ); } /** Get Above QpMinCu *\param uiAPartUnitIdx *\param uiCurrAbsIdxInCtu *\returns TComDataCU* point of TComDataCU of above QpMinCu */ const TComDataCU* TComDataCU::getQpMinCuAbove( UInt& uiAPartUnitIdx, UInt uiCurrAbsIdxInCtu ) const { const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); const UInt maxCUDepth = getSlice()->getSPS()->getMaxTotalCUDepth(); const UInt maxCuDQPDepth = getSlice()->getPPS()->getMaxCuDQPDepth(); const UInt doubleDepthDifference = ((maxCUDepth - maxCuDQPDepth)<<1); UInt absZorderQpMinCUIdx = (uiCurrAbsIdxInCtu>>doubleDepthDifference)<getCtu( getCtuRsAddr() ); } /** Get reference QP from left QpMinCu or latest coded QP *\param uiCurrAbsIdxInCtu *\returns SChar reference QP value */ SChar TComDataCU::getRefQP( UInt uiCurrAbsIdxInCtu ) const { UInt lPartIdx = MAX_UINT; UInt aPartIdx = MAX_UINT; const TComDataCU* cULeft = getQpMinCuLeft ( lPartIdx, m_absZIdxInCtu + uiCurrAbsIdxInCtu ); const TComDataCU* cUAbove = getQpMinCuAbove( aPartIdx, m_absZIdxInCtu + uiCurrAbsIdxInCtu ); return (((cULeft? cULeft->getQP( lPartIdx ): getLastCodedQP( uiCurrAbsIdxInCtu )) + (cUAbove? cUAbove->getQP( aPartIdx ): getLastCodedQP( uiCurrAbsIdxInCtu )) + 1) >> 1); } Int TComDataCU::getLastValidPartIdx( Int iAbsPartIdx ) const { Int iLastValidPartIdx = iAbsPartIdx-1; while ( iLastValidPartIdx >= 0 && getPredictionMode( iLastValidPartIdx ) == NUMBER_OF_PREDICTION_MODES ) { UInt uiDepth = getDepth( iLastValidPartIdx ); iLastValidPartIdx -= m_uiNumPartition>>(uiDepth<<1); } return iLastValidPartIdx; } SChar TComDataCU::getLastCodedQP( UInt uiAbsPartIdx ) const { UInt uiQUPartIdxMask = ~((1<<((getSlice()->getSPS()->getMaxTotalCUDepth() - getSlice()->getPPS()->getMaxCuDQPDepth())<<1))-1); Int iLastValidPartIdx = getLastValidPartIdx( uiAbsPartIdx&uiQUPartIdxMask ); // A idx will be invalid if it is off the right or bottom edge of the picture. // If this CU is in the first CTU of the slice and there is no valid part before this one, use slice QP if ( getPic()->getPicSym()->getCtuTsToRsAddrMap(getSlice()->getSliceCurStartCtuTsAddr()) == getCtuRsAddr() && Int(getZorderIdxInCtu())+iLastValidPartIdx<0) { return getSlice()->getSliceQp(); } else if ( iLastValidPartIdx >= 0 ) { // If there is a valid part within the current Sub-CU, use it return getQP( iLastValidPartIdx ); } else { if ( getZorderIdxInCtu() > 0 ) { // If this wasn't the first sub-cu within the Ctu, explore the CTU itself. return getPic()->getCtu( getCtuRsAddr() )->getLastCodedQP( getZorderIdxInCtu() ); // TODO - remove this recursion } else if ( getPic()->getPicSym()->getCtuRsToTsAddrMap(getCtuRsAddr()) > 0 && CUIsFromSameSliceTileAndWavefrontRow(getPic()->getCtu(getPic()->getPicSym()->getCtuTsToRsAddrMap(getPic()->getPicSym()->getCtuRsToTsAddrMap(getCtuRsAddr())-1))) ) { // If this isn't the first Ctu (how can it be due to the first 'if'?), and the previous Ctu is from the same tile, examine the previous Ctu. return getPic()->getCtu( getPic()->getPicSym()->getCtuTsToRsAddrMap(getPic()->getPicSym()->getCtuRsToTsAddrMap(getCtuRsAddr())-1) )->getLastCodedQP( getPic()->getNumPartitionsInCtu() ); // TODO - remove this recursion } else { // No other options available - use the slice-level QP. return getSlice()->getSliceQp(); } } } /** Check whether the CU is coded in lossless coding mode. * \param absPartIdx * \returns true if the CU is coded in lossless coding mode; false if otherwise */ Bool TComDataCU::isLosslessCoded(UInt absPartIdx) const { return (getSlice()->getPPS()->getTransquantBypassEnabledFlag() && getCUTransquantBypass (absPartIdx)); } /** Get allowed chroma intra modes * - fills uiModeList with chroma intra modes * *\param [in] uiAbsPartIdx *\param [out] uiModeList pointer to chroma intra modes array */ Void TComDataCU::getAllowedChromaDir( UInt uiAbsPartIdx, UInt uiModeList[NUM_CHROMA_MODE] ) const { uiModeList[0] = PLANAR_IDX; uiModeList[1] = VER_IDX; uiModeList[2] = HOR_IDX; uiModeList[3] = DC_IDX; uiModeList[4] = DM_CHROMA_IDX; assert(4getSPS(); const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())); const ChannelType chType = toChannelType(compID); const ChromaFormat chForm = getPic()->getChromaFormat(); // Get intra direction of left PU const TComDataCU *pcCULeft = getPULeft( LeftPartIdx, m_absZIdxInCtu + uiAbsPartIdx ); if (isChroma(compID)) { LeftPartIdx = getChromasCorrespondingPULumaIdx(LeftPartIdx, chForm, partsPerMinCU); } iLeftIntraDir = pcCULeft ? ( pcCULeft->isIntra( LeftPartIdx ) ? pcCULeft->getIntraDir( chType, LeftPartIdx ) : DC_IDX ) : DC_IDX; // Get intra direction of above PU const TComDataCU *pcCUAbove = getPUAbove( AbovePartIdx, m_absZIdxInCtu + uiAbsPartIdx, true, true ); if (isChroma(compID)) { AbovePartIdx = getChromasCorrespondingPULumaIdx(AbovePartIdx, chForm, partsPerMinCU); } iAboveIntraDir = pcCUAbove ? ( pcCUAbove->isIntra( AbovePartIdx ) ? pcCUAbove->getIntraDir( chType, AbovePartIdx ) : DC_IDX ) : DC_IDX; if (isChroma(chType)) { if (iLeftIntraDir == DM_CHROMA_IDX) { iLeftIntraDir = pcCULeft-> getIntraDir( CHANNEL_TYPE_LUMA, LeftPartIdx ); } if (iAboveIntraDir == DM_CHROMA_IDX) { iAboveIntraDir = pcCUAbove->getIntraDir( CHANNEL_TYPE_LUMA, AbovePartIdx ); } } assert (2 1) // angular modes { uiIntraDirPred[0] = iLeftIntraDir; uiIntraDirPred[1] = ((iLeftIntraDir + 29) % 32) + 2; uiIntraDirPred[2] = ((iLeftIntraDir - 1 ) % 32) + 2; } else //non-angular { uiIntraDirPred[0] = PLANAR_IDX; uiIntraDirPred[1] = DC_IDX; uiIntraDirPred[2] = VER_IDX; } } else { if( piMode ) { *piMode = 2; } uiIntraDirPred[0] = iLeftIntraDir; uiIntraDirPred[1] = iAboveIntraDir; if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar { uiIntraDirPred[2] = PLANAR_IDX; } else { uiIntraDirPred[2] = (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX; } } for (UInt i=0; igetDepth( uiTempPartIdx ) > uiDepth ) ? 1 : 0 ) : 0; // Get above split flag pcTempCU = getPUAbove( uiTempPartIdx, m_absZIdxInCtu + uiAbsPartIdx ); uiCtx += ( pcTempCU ) ? ( ( pcTempCU->getDepth( uiTempPartIdx ) > uiDepth ) ? 1 : 0 ) : 0; return uiCtx; } UInt TComDataCU::getCtxQtCbf( TComTU &rTu, const ChannelType chType ) const { const UInt transformDepth = rTu.GetTransformDepthRel(); if (isChroma(chType)) { return transformDepth; } else { const UInt uiCtx = ( transformDepth == 0 ? 1 : 0 ); return uiCtx; } } UInt TComDataCU::getQuadtreeTULog2MinSizeInCU( UInt absPartIdx ) const { UInt log2CbSize = g_aucConvertToBit[getWidth( absPartIdx )] + 2; PartSize partSize = getPartitionSize( absPartIdx ); UInt quadtreeTUMaxDepth = isIntra( absPartIdx ) ? m_pcSlice->getSPS()->getQuadtreeTUMaxDepthIntra() : m_pcSlice->getSPS()->getQuadtreeTUMaxDepthInter(); Int intraSplitFlag = ( isIntra( absPartIdx ) && partSize == SIZE_NxN ) ? 1 : 0; Int interSplitFlag = ((quadtreeTUMaxDepth == 1) && isInter( absPartIdx ) && (partSize != SIZE_2Nx2N) ); UInt log2MinTUSizeInCU = 0; if (log2CbSize < (m_pcSlice->getSPS()->getQuadtreeTULog2MinSize() + quadtreeTUMaxDepth - 1 + interSplitFlag + intraSplitFlag) ) { // when fully making use of signaled TUMaxDepth + inter/intraSplitFlag, resulting luma TB size is < QuadtreeTULog2MinSize log2MinTUSizeInCU = m_pcSlice->getSPS()->getQuadtreeTULog2MinSize(); } else { // when fully making use of signaled TUMaxDepth + inter/intraSplitFlag, resulting luma TB size is still >= QuadtreeTULog2MinSize log2MinTUSizeInCU = log2CbSize - ( quadtreeTUMaxDepth - 1 + interSplitFlag + intraSplitFlag); // stop when trafoDepth == hierarchy_depth = splitFlag if ( log2MinTUSizeInCU > m_pcSlice->getSPS()->getQuadtreeTULog2MaxSize()) { // when fully making use of signaled TUMaxDepth + inter/intraSplitFlag, resulting luma TB size is still > QuadtreeTULog2MaxSize log2MinTUSizeInCU = m_pcSlice->getSPS()->getQuadtreeTULog2MaxSize(); } } return log2MinTUSizeInCU; } UInt TComDataCU::getCtxSkipFlag( UInt uiAbsPartIdx ) const { const TComDataCU* pcTempCU; UInt uiTempPartIdx; UInt uiCtx = 0; // Get BCBP of left PU pcTempCU = getPULeft( uiTempPartIdx, m_absZIdxInCtu + uiAbsPartIdx ); uiCtx = ( pcTempCU ) ? pcTempCU->isSkipped( uiTempPartIdx ) : 0; // Get BCBP of above PU pcTempCU = getPUAbove( uiTempPartIdx, m_absZIdxInCtu + uiAbsPartIdx ); uiCtx += ( pcTempCU ) ? pcTempCU->isSkipped( uiTempPartIdx ) : 0; return uiCtx; } UInt TComDataCU::getCtxInterDir( UInt uiAbsPartIdx ) const { return getDepth( uiAbsPartIdx ); } UChar TComDataCU::getQtRootCbf( UInt uiIdx ) const { const UInt numberValidComponents = getPic()->getNumberValidComponents(); return getCbf( uiIdx, COMPONENT_Y, 0 ) || ((numberValidComponents > COMPONENT_Cb) && getCbf( uiIdx, COMPONENT_Cb, 0 )) || ((numberValidComponents > COMPONENT_Cr) && getCbf( uiIdx, COMPONENT_Cr, 0 )); } Void TComDataCU::setCbfSubParts( const UInt uiCbf[MAX_NUM_COMPONENT], UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); for(UInt comp=0; compgetNumPartitionsInCtu() >> (uiDepth << 1); memset( m_puhCbf[compID] + uiAbsPartIdx, uiCbf, sizeof( UChar ) * uiCurrPartNumb ); } /** Sets a coded block flag for all sub-partitions of a partition * \param uiCbf The value of the coded block flag to be set * \param compID * \param uiAbsPartIdx * \param uiPartIdx * \param uiDepth */ Void TComDataCU::setCbfSubParts ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( uiCbf, m_puhCbf[compID], uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setCbfPartRange ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ) { memset((m_puhCbf[compID] + uiAbsPartIdx), uiCbf, (sizeof(UChar) * uiCoveredPartIdxes)); } Void TComDataCU::bitwiseOrCbfPartRange( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ) { const UInt stopAbsPartIdx = uiAbsPartIdx + uiCoveredPartIdxes; for (UInt subPartIdx = uiAbsPartIdx; subPartIdx < stopAbsPartIdx; subPartIdx++) { m_puhCbf[compID][subPartIdx] |= uiCbf; } } Void TComDataCU::setDepthSubParts( UInt uiDepth, UInt uiAbsPartIdx ) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); memset( m_puhDepth + uiAbsPartIdx, uiDepth, sizeof(UChar)*uiCurrPartNumb ); } Bool TComDataCU::isFirstAbsZorderIdxInDepth (UInt uiAbsPartIdx, UInt uiDepth) const { UInt uiPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); return (((m_absZIdxInCtu + uiAbsPartIdx)% uiPartNumb) == 0); } Void TComDataCU::setPartSizeSubParts( PartSize eMode, UInt uiAbsPartIdx, UInt uiDepth ) { assert( sizeof( *m_pePartSize) == 1 ); memset( m_pePartSize + uiAbsPartIdx, eMode, m_pcPic->getNumPartitionsInCtu() >> ( 2 * uiDepth ) ); } Void TComDataCU::setCUTransquantBypassSubParts( Bool flag, UInt uiAbsPartIdx, UInt uiDepth ) { memset( m_CUTransquantBypass + uiAbsPartIdx, flag, m_pcPic->getNumPartitionsInCtu() >> ( 2 * uiDepth ) ); } Void TComDataCU::setSkipFlagSubParts( Bool skip, UInt absPartIdx, UInt depth ) { assert( sizeof( *m_skipFlag) == 1 ); memset( m_skipFlag + absPartIdx, skip, m_pcPic->getNumPartitionsInCtu() >> ( 2 * depth ) ); } Void TComDataCU::setPredModeSubParts( PredMode eMode, UInt uiAbsPartIdx, UInt uiDepth ) { assert( sizeof( *m_pePredMode) == 1 ); memset( m_pePredMode + uiAbsPartIdx, eMode, m_pcPic->getNumPartitionsInCtu() >> ( 2 * uiDepth ) ); } Void TComDataCU::setChromaQpAdjSubParts( UChar val, Int absPartIdx, Int depth ) { assert( sizeof(*m_ChromaQpAdj) == 1 ); memset( m_ChromaQpAdj + absPartIdx, val, m_pcPic->getNumPartitionsInCtu() >> ( 2 * depth ) ); } Void TComDataCU::setQPSubCUs( Int qp, UInt absPartIdx, UInt depth, Bool &foundNonZeroCbf ) { UInt currPartNumb = m_pcPic->getNumPartitionsInCtu() >> (depth << 1); UInt currPartNumQ = currPartNumb >> 2; const UInt numValidComp = m_pcPic->getNumberValidComponents(); if(!foundNonZeroCbf) { if(getDepth(absPartIdx) > depth) { for ( UInt partUnitIdx = 0; partUnitIdx < 4; partUnitIdx++ ) { setQPSubCUs( qp, absPartIdx+partUnitIdx*currPartNumQ, depth+1, foundNonZeroCbf ); } } else { if(getCbf( absPartIdx, COMPONENT_Y ) || (numValidComp>COMPONENT_Cb && getCbf( absPartIdx, COMPONENT_Cb )) || (numValidComp>COMPONENT_Cr && getCbf( absPartIdx, COMPONENT_Cr) ) ) { foundNonZeroCbf = true; } else { setQPSubParts(qp, absPartIdx, depth); } } } } Void TComDataCU::setQPSubParts( Int qp, UInt uiAbsPartIdx, UInt uiDepth ) { const UInt numPart = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); memset(m_phQP+uiAbsPartIdx, qp, numPart); } Void TComDataCU::setIntraDirSubParts( const ChannelType channelType, const UInt dir, const UInt absPartIdx, const UInt depth ) { UInt numPart = m_pcPic->getNumPartitionsInCtu() >> (depth << 1); memset( m_puhIntraDir[channelType] + absPartIdx, dir,sizeof(UChar)*numPart ); } template Void TComDataCU::setSubPart( T uiParameter, T* puhBaseCtu, UInt uiCUAddr, UInt uiCUDepth, UInt uiPUIdx ) { assert( sizeof(T) == 1 ); // Using memset() works only for types of size 1 UInt uiCurrPartNumQ = (m_pcPic->getNumPartitionsInCtu() >> (2 * uiCUDepth)) >> 2; switch ( m_pePartSize[ uiCUAddr ] ) { case SIZE_2Nx2N: memset( puhBaseCtu + uiCUAddr, uiParameter, 4 * uiCurrPartNumQ ); break; case SIZE_2NxN: memset( puhBaseCtu + uiCUAddr, uiParameter, 2 * uiCurrPartNumQ ); break; case SIZE_Nx2N: memset( puhBaseCtu + uiCUAddr, uiParameter, uiCurrPartNumQ ); memset( puhBaseCtu + uiCUAddr + 2 * uiCurrPartNumQ, uiParameter, uiCurrPartNumQ ); break; case SIZE_NxN: memset( puhBaseCtu + uiCUAddr, uiParameter, uiCurrPartNumQ ); break; case SIZE_2NxnU: if ( uiPUIdx == 0 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 1) ); memset( puhBaseCtu + uiCUAddr + uiCurrPartNumQ, uiParameter, (uiCurrPartNumQ >> 1) ); } else if ( uiPUIdx == 1 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 1) ); memset( puhBaseCtu + uiCUAddr + uiCurrPartNumQ, uiParameter, ((uiCurrPartNumQ >> 1) + (uiCurrPartNumQ << 1)) ); } else { assert(0); } break; case SIZE_2NxnD: if ( uiPUIdx == 0 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, ((uiCurrPartNumQ << 1) + (uiCurrPartNumQ >> 1)) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1) + uiCurrPartNumQ, uiParameter, (uiCurrPartNumQ >> 1) ); } else if ( uiPUIdx == 1 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 1) ); memset( puhBaseCtu + uiCUAddr + uiCurrPartNumQ, uiParameter, (uiCurrPartNumQ >> 1) ); } else { assert(0); } break; case SIZE_nLx2N: if ( uiPUIdx == 0 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1) + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); } else if ( uiPUIdx == 1 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ + (uiCurrPartNumQ >> 2)) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1) + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ + (uiCurrPartNumQ >> 2)) ); } else { assert(0); } break; case SIZE_nRx2N: if ( uiPUIdx == 0 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ + (uiCurrPartNumQ >> 2)) ); memset( puhBaseCtu + uiCUAddr + uiCurrPartNumQ + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1), uiParameter, (uiCurrPartNumQ + (uiCurrPartNumQ >> 2)) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1) + uiCurrPartNumQ + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); } else if ( uiPUIdx == 1 ) { memset( puhBaseCtu + uiCUAddr, uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1), uiParameter, (uiCurrPartNumQ >> 2) ); memset( puhBaseCtu + uiCUAddr + (uiCurrPartNumQ << 1) + (uiCurrPartNumQ >> 1), uiParameter, (uiCurrPartNumQ >> 2) ); } else { assert(0); } break; default: assert( 0 ); break; } } Void TComDataCU::setMergeFlagSubParts ( Bool bMergeFlag, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( bMergeFlag, m_pbMergeFlag, uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setMergeIndexSubParts ( UInt uiMergeIndex, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( uiMergeIndex, m_puhMergeIndex, uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setInterDirSubParts( UInt uiDir, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( uiDir, m_puhInterDir, uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setMVPIdxSubParts( Int iMVPIdx, RefPicList eRefPicList, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( iMVPIdx, m_apiMVPIdx[eRefPicList], uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setMVPNumSubParts( Int iMVPNum, RefPicList eRefPicList, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) { setSubPart( iMVPNum, m_apiMVPNum[eRefPicList], uiAbsPartIdx, uiDepth, uiPartIdx ); } Void TComDataCU::setTrIdxSubParts( UInt uiTrIdx, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); memset( m_puhTrIdx + uiAbsPartIdx, uiTrIdx, sizeof(UChar)*uiCurrPartNumb ); } Void TComDataCU::setTransformSkipSubParts( const UInt useTransformSkip[MAX_NUM_COMPONENT], UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); for(UInt i=0; igetNumPartitionsInCtu() >> (uiDepth << 1); memset( m_puhTransformSkip[compID] + uiAbsPartIdx, useTransformSkip, sizeof( UChar ) * uiCurrPartNumb ); } Void TComDataCU::setTransformSkipPartRange ( UInt useTransformSkip, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ) { memset((m_puhTransformSkip[compID] + uiAbsPartIdx), useTransformSkip, (sizeof(UChar) * uiCoveredPartIdxes)); } Void TComDataCU::setCrossComponentPredictionAlphaPartRange( SChar alphaValue, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ) { memset((m_crossComponentPredictionAlpha[compID] + uiAbsPartIdx), alphaValue, (sizeof(SChar) * uiCoveredPartIdxes)); } Void TComDataCU::setExplicitRdpcmModePartRange ( UInt rdpcmMode, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ) { memset((m_explicitRdpcmMode[compID] + uiAbsPartIdx), rdpcmMode, (sizeof(UChar) * uiCoveredPartIdxes)); } Void TComDataCU::setSizeSubParts( UInt uiWidth, UInt uiHeight, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); memset( m_puhWidth + uiAbsPartIdx, uiWidth, sizeof(UChar)*uiCurrPartNumb ); memset( m_puhHeight + uiAbsPartIdx, uiHeight, sizeof(UChar)*uiCurrPartNumb ); } UChar TComDataCU::getNumPartitions(const UInt uiAbsPartIdx) const { UChar iNumPart = 0; switch ( m_pePartSize[uiAbsPartIdx] ) { case SIZE_2Nx2N: iNumPart = 1; break; case SIZE_2NxN: iNumPart = 2; break; case SIZE_Nx2N: iNumPart = 2; break; case SIZE_NxN: iNumPart = 4; break; case SIZE_2NxnU: iNumPart = 2; break; case SIZE_2NxnD: iNumPart = 2; break; case SIZE_nLx2N: iNumPart = 2; break; case SIZE_nRx2N: iNumPart = 2; break; default: assert (0); break; } return iNumPart; } // This is for use by a leaf/sub CU object only, with no additional AbsPartIdx Void TComDataCU::getPartIndexAndSize( UInt uiPartIdx, UInt& ruiPartAddr, Int& riWidth, Int& riHeight ) const { switch ( m_pePartSize[0] ) { case SIZE_2NxN: riWidth = getWidth(0); riHeight = getHeight(0) >> 1; ruiPartAddr = ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 1; break; case SIZE_Nx2N: riWidth = getWidth(0) >> 1; riHeight = getHeight(0); ruiPartAddr = ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 2; break; case SIZE_NxN: riWidth = getWidth(0) >> 1; riHeight = getHeight(0) >> 1; ruiPartAddr = ( m_uiNumPartition >> 2 ) * uiPartIdx; break; case SIZE_2NxnU: riWidth = getWidth(0); riHeight = ( uiPartIdx == 0 ) ? getHeight(0) >> 2 : ( getHeight(0) >> 2 ) + ( getHeight(0) >> 1 ); ruiPartAddr = ( uiPartIdx == 0 ) ? 0 : m_uiNumPartition >> 3; break; case SIZE_2NxnD: riWidth = getWidth(0); riHeight = ( uiPartIdx == 0 ) ? ( getHeight(0) >> 2 ) + ( getHeight(0) >> 1 ) : getHeight(0) >> 2; ruiPartAddr = ( uiPartIdx == 0 ) ? 0 : (m_uiNumPartition >> 1) + (m_uiNumPartition >> 3); break; case SIZE_nLx2N: riWidth = ( uiPartIdx == 0 ) ? getWidth(0) >> 2 : ( getWidth(0) >> 2 ) + ( getWidth(0) >> 1 ); riHeight = getHeight(0); ruiPartAddr = ( uiPartIdx == 0 ) ? 0 : m_uiNumPartition >> 4; break; case SIZE_nRx2N: riWidth = ( uiPartIdx == 0 ) ? ( getWidth(0) >> 2 ) + ( getWidth(0) >> 1 ) : getWidth(0) >> 2; riHeight = getHeight(0); ruiPartAddr = ( uiPartIdx == 0 ) ? 0 : (m_uiNumPartition >> 2) + (m_uiNumPartition >> 4); break; default: assert ( m_pePartSize[0] == SIZE_2Nx2N ); riWidth = getWidth(0); riHeight = getHeight(0); ruiPartAddr = 0; break; } } // static member function Void TComDataCU::getMvField ( const TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefPicList, TComMvField& rcMvField ) { if ( pcCU == NULL ) // OUT OF BOUNDARY { TComMv cZeroMv; rcMvField.setMvField( cZeroMv, NOT_VALID ); return; } const TComCUMvField* pcCUMvField = pcCU->getCUMvField( eRefPicList ); rcMvField.setMvField( pcCUMvField->getMv( uiAbsPartIdx ), pcCUMvField->getRefIdx( uiAbsPartIdx ) ); } Void TComDataCU::deriveLeftRightTopIdxGeneral ( UInt uiAbsPartIdx, UInt uiPartIdx, UInt& ruiPartIdxLT, UInt& ruiPartIdxRT ) const { ruiPartIdxLT = m_absZIdxInCtu + uiAbsPartIdx; UInt uiPUWidth = 0; switch ( m_pePartSize[uiAbsPartIdx] ) { case SIZE_2Nx2N: uiPUWidth = m_puhWidth[uiAbsPartIdx]; break; case SIZE_2NxN: uiPUWidth = m_puhWidth[uiAbsPartIdx]; break; case SIZE_Nx2N: uiPUWidth = m_puhWidth[uiAbsPartIdx] >> 1; break; case SIZE_NxN: uiPUWidth = m_puhWidth[uiAbsPartIdx] >> 1; break; case SIZE_2NxnU: uiPUWidth = m_puhWidth[uiAbsPartIdx]; break; case SIZE_2NxnD: uiPUWidth = m_puhWidth[uiAbsPartIdx]; break; case SIZE_nLx2N: if ( uiPartIdx == 0 ) { uiPUWidth = m_puhWidth[uiAbsPartIdx] >> 2; } else if ( uiPartIdx == 1 ) { uiPUWidth = (m_puhWidth[uiAbsPartIdx] >> 1) + (m_puhWidth[uiAbsPartIdx] >> 2); } else { assert(0); } break; case SIZE_nRx2N: if ( uiPartIdx == 0 ) { uiPUWidth = (m_puhWidth[uiAbsPartIdx] >> 1) + (m_puhWidth[uiAbsPartIdx] >> 2); } else if ( uiPartIdx == 1 ) { uiPUWidth = m_puhWidth[uiAbsPartIdx] >> 2; } else { assert(0); } break; default: assert (0); break; } ruiPartIdxRT = g_auiRasterToZscan [g_auiZscanToRaster[ ruiPartIdxLT ] + uiPUWidth / m_pcPic->getMinCUWidth() - 1 ]; } Void TComDataCU::deriveLeftBottomIdxGeneral( UInt uiAbsPartIdx, UInt uiPartIdx, UInt& ruiPartIdxLB ) const { UInt uiPUHeight = 0; switch ( m_pePartSize[uiAbsPartIdx] ) { case SIZE_2Nx2N: uiPUHeight = m_puhHeight[uiAbsPartIdx]; break; case SIZE_2NxN: uiPUHeight = m_puhHeight[uiAbsPartIdx] >> 1; break; case SIZE_Nx2N: uiPUHeight = m_puhHeight[uiAbsPartIdx]; break; case SIZE_NxN: uiPUHeight = m_puhHeight[uiAbsPartIdx] >> 1; break; case SIZE_2NxnU: if ( uiPartIdx == 0 ) { uiPUHeight = m_puhHeight[uiAbsPartIdx] >> 2; } else if ( uiPartIdx == 1 ) { uiPUHeight = (m_puhHeight[uiAbsPartIdx] >> 1) + (m_puhHeight[uiAbsPartIdx] >> 2); } else { assert(0); } break; case SIZE_2NxnD: if ( uiPartIdx == 0 ) { uiPUHeight = (m_puhHeight[uiAbsPartIdx] >> 1) + (m_puhHeight[uiAbsPartIdx] >> 2); } else if ( uiPartIdx == 1 ) { uiPUHeight = m_puhHeight[uiAbsPartIdx] >> 2; } else { assert(0); } break; case SIZE_nLx2N: uiPUHeight = m_puhHeight[uiAbsPartIdx]; break; case SIZE_nRx2N: uiPUHeight = m_puhHeight[uiAbsPartIdx]; break; default: assert (0); break; } ruiPartIdxLB = g_auiRasterToZscan [g_auiZscanToRaster[ m_absZIdxInCtu + uiAbsPartIdx ] + ((uiPUHeight / m_pcPic->getMinCUHeight()) - 1)*m_pcPic->getNumPartInCtuWidth()]; } Void TComDataCU::deriveLeftRightTopIdx ( UInt uiPartIdx, UInt& ruiPartIdxLT, UInt& ruiPartIdxRT ) const { ruiPartIdxLT = m_absZIdxInCtu; ruiPartIdxRT = g_auiRasterToZscan [g_auiZscanToRaster[ ruiPartIdxLT ] + m_puhWidth[0] / m_pcPic->getMinCUWidth() - 1 ]; switch ( m_pePartSize[0] ) { case SIZE_2Nx2N: break; case SIZE_2NxN: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 1; ruiPartIdxRT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 1; break; case SIZE_Nx2N: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 2; ruiPartIdxRT -= ( uiPartIdx == 1 )? 0 : m_uiNumPartition >> 2; break; case SIZE_NxN: ruiPartIdxLT += ( m_uiNumPartition >> 2 ) * uiPartIdx; ruiPartIdxRT += ( m_uiNumPartition >> 2 ) * ( uiPartIdx - 1 ); break; case SIZE_2NxnU: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 3; ruiPartIdxRT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 3; break; case SIZE_2NxnD: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : ( m_uiNumPartition >> 1 ) + ( m_uiNumPartition >> 3 ); ruiPartIdxRT += ( uiPartIdx == 0 )? 0 : ( m_uiNumPartition >> 1 ) + ( m_uiNumPartition >> 3 ); break; case SIZE_nLx2N: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 4; ruiPartIdxRT -= ( uiPartIdx == 1 )? 0 : ( m_uiNumPartition >> 2 ) + ( m_uiNumPartition >> 4 ); break; case SIZE_nRx2N: ruiPartIdxLT += ( uiPartIdx == 0 )? 0 : ( m_uiNumPartition >> 2 ) + ( m_uiNumPartition >> 4 ); ruiPartIdxRT -= ( uiPartIdx == 1 )? 0 : m_uiNumPartition >> 4; break; default: assert (0); break; } } Void TComDataCU::deriveLeftBottomIdx( UInt uiPartIdx, UInt& ruiPartIdxLB ) const { ruiPartIdxLB = g_auiRasterToZscan [g_auiZscanToRaster[ m_absZIdxInCtu ] + ( ((m_puhHeight[0] / m_pcPic->getMinCUHeight())>>1) - 1)*m_pcPic->getNumPartInCtuWidth()]; switch ( m_pePartSize[0] ) { case SIZE_2Nx2N: ruiPartIdxLB += m_uiNumPartition >> 1; break; case SIZE_2NxN: ruiPartIdxLB += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 1; break; case SIZE_Nx2N: ruiPartIdxLB += ( uiPartIdx == 0 )? m_uiNumPartition >> 1 : (m_uiNumPartition >> 2)*3; break; case SIZE_NxN: ruiPartIdxLB += ( m_uiNumPartition >> 2 ) * uiPartIdx; break; case SIZE_2NxnU: ruiPartIdxLB += ( uiPartIdx == 0 ) ? -((Int)m_uiNumPartition >> 3) : m_uiNumPartition >> 1; break; case SIZE_2NxnD: ruiPartIdxLB += ( uiPartIdx == 0 ) ? (m_uiNumPartition >> 2) + (m_uiNumPartition >> 3): m_uiNumPartition >> 1; break; case SIZE_nLx2N: ruiPartIdxLB += ( uiPartIdx == 0 ) ? m_uiNumPartition >> 1 : (m_uiNumPartition >> 1) + (m_uiNumPartition >> 4); break; case SIZE_nRx2N: ruiPartIdxLB += ( uiPartIdx == 0 ) ? m_uiNumPartition >> 1 : (m_uiNumPartition >> 1) + (m_uiNumPartition >> 2) + (m_uiNumPartition >> 4); break; default: assert (0); break; } } /** Derive the partition index of neighbouring bottom right block * \param [in] uiPartIdx current partition index * \param [out] ruiPartIdxRB partition index of neighbouring bottom right block */ Void TComDataCU::deriveRightBottomIdx( UInt uiPartIdx, UInt &ruiPartIdxRB ) const { ruiPartIdxRB = g_auiRasterToZscan [g_auiZscanToRaster[ m_absZIdxInCtu ] + ( ((m_puhHeight[0] / m_pcPic->getMinCUHeight())>>1) - 1)*m_pcPic->getNumPartInCtuWidth() + m_puhWidth[0] / m_pcPic->getMinCUWidth() - 1]; switch ( m_pePartSize[0] ) { case SIZE_2Nx2N: ruiPartIdxRB += m_uiNumPartition >> 1; break; case SIZE_2NxN: ruiPartIdxRB += ( uiPartIdx == 0 )? 0 : m_uiNumPartition >> 1; break; case SIZE_Nx2N: ruiPartIdxRB += ( uiPartIdx == 0 )? m_uiNumPartition >> 2 : (m_uiNumPartition >> 1); break; case SIZE_NxN: ruiPartIdxRB += ( m_uiNumPartition >> 2 ) * ( uiPartIdx - 1 ); break; case SIZE_2NxnU: ruiPartIdxRB += ( uiPartIdx == 0 ) ? -((Int)m_uiNumPartition >> 3) : m_uiNumPartition >> 1; break; case SIZE_2NxnD: ruiPartIdxRB += ( uiPartIdx == 0 ) ? (m_uiNumPartition >> 2) + (m_uiNumPartition >> 3): m_uiNumPartition >> 1; break; case SIZE_nLx2N: ruiPartIdxRB += ( uiPartIdx == 0 ) ? (m_uiNumPartition >> 3) + (m_uiNumPartition >> 4): m_uiNumPartition >> 1; break; case SIZE_nRx2N: ruiPartIdxRB += ( uiPartIdx == 0 ) ? (m_uiNumPartition >> 2) + (m_uiNumPartition >> 3) + (m_uiNumPartition >> 4) : m_uiNumPartition >> 1; break; default: assert (0); break; } } Bool TComDataCU::hasEqualMotion( UInt uiAbsPartIdx, const TComDataCU* pcCandCU, UInt uiCandAbsPartIdx ) const { if ( getInterDir( uiAbsPartIdx ) != pcCandCU->getInterDir( uiCandAbsPartIdx ) ) { return false; } for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( getInterDir( uiAbsPartIdx ) & ( 1 << uiRefListIdx ) ) { if ( getCUMvField( RefPicList( uiRefListIdx ) )->getMv( uiAbsPartIdx ) != pcCandCU->getCUMvField( RefPicList( uiRefListIdx ) )->getMv( uiCandAbsPartIdx ) || getCUMvField( RefPicList( uiRefListIdx ) )->getRefIdx( uiAbsPartIdx ) != pcCandCU->getCUMvField( RefPicList( uiRefListIdx ) )->getRefIdx( uiCandAbsPartIdx ) ) { return false; } } } return true; } //! Construct a list of merging candidates #if MCTS_ENC_CHECK Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, UInt &numSpatialMergeCandidates, Int mrgCandIdx ) const #else Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx ) const #endif { UInt uiAbsPartAddr = m_absZIdxInCtu + uiAbsPartIdx; Bool abCandIsInter[ MRG_MAX_NUM_CANDS ]; for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) { abCandIsInter[ui] = false; pcMvFieldNeighbours[ ( ui << 1 ) ].setRefIdx(NOT_VALID); pcMvFieldNeighbours[ ( ui << 1 ) + 1 ].setRefIdx(NOT_VALID); } numValidMergeCand = getSlice()->getMaxNumMergeCand(); // compute the location of the current PU Int xP, yP, nPSW, nPSH; this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH); Int iCount = 0; UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB; PartSize cCurPS = getPartitionSize( uiAbsPartIdx ); deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT ); deriveLeftBottomIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLB ); //left UInt uiLeftPartIdx = 0; const TComDataCU *pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB ); Bool isAvailableA1 = pcCULeft && pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && !( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) && pcCULeft->isInter( uiLeftPartIdx ) ; if ( isAvailableA1 ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount + 1; #endif return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif return; } // above UInt uiAbovePartIdx = 0; const TComDataCU *pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT ); Bool isAvailableB1 = pcCUAbove && pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) && !( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) && pcCUAbove->isInter( uiAbovePartIdx ); if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount + 1; #endif return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif return; } // above right UInt uiAboveRightPartIdx = 0; const TComDataCU *pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT ); Bool isAvailableB0 = pcCUAboveRight && pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) && pcCUAboveRight->isInter( uiAboveRightPartIdx ); if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount + 1; #endif return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif return; } //left bottom UInt uiLeftBottomPartIdx = 0; const TComDataCU *pcCULeftBottom = this->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB ); Bool isAvailableA0 = pcCULeftBottom && pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) && pcCULeftBottom->isInter( uiLeftBottomPartIdx ) ; if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount + 1; #endif return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif return; } // above left if( iCount < 4 ) { UInt uiAboveLeftPartIdx = 0; const TComDataCU *pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr ); Bool isAvailableB2 = pcCUAboveLeft && pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) && pcCUAboveLeft->isInter( uiAboveLeftPartIdx ); if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount + 1; #endif return; } iCount ++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif return; } #if MCTS_ENC_CHECK numSpatialMergeCandidates = iCount; #endif if ( getSlice()->getEnableTMVPFlag() ) { //>> MTK colocated-RightBottom UInt uiPartIdxRB; deriveRightBottomIdx( uiPUIdx, uiPartIdxRB ); UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); const UInt numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight(); TComMv cColMv; Int iRefIdx; Int ctuRsAddr = -1; if ( ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () ) // image boundary check && ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) ) { if ( ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) && // is not at the last column of CTU ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) ) // is not at the last row of CTU { uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + numPartInCtuWidth + 1 ]; ctuRsAddr = getCtuRsAddr(); } else if ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) // is not at the last column of CTU But is last row of CTU { uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ]; } else if ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) // is not at the last row of CTU But is last column of CTU { uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ]; ctuRsAddr = getCtuRsAddr() + 1; } else //is the right bottom corner of CTU { uiAbsPartAddr = 0; } } iRefIdx = 0; Bool bExistMV = false; UInt uiPartIdxCenter; Int dir = 0; UInt uiArrayAddr = iCount; xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter ); bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_0, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx ); if( bExistMV == false ) { bExistMV = xGetColMVP( REF_PIC_LIST_0, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx ); } if( bExistMV ) { dir |= 1; pcMvFieldNeighbours[ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx ); } if ( getSlice()->isInterB() ) { bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_1, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx); if( bExistMV == false ) { bExistMV = xGetColMVP( REF_PIC_LIST_1, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx ); } if( bExistMV ) { dir |= 2; pcMvFieldNeighbours[ 2 * uiArrayAddr + 1 ].setMvField( cColMv, iRefIdx ); } } if (dir != 0) { puhInterDirNeighbours[uiArrayAddr] = dir; abCandIsInter[uiArrayAddr] = true; if ( mrgCandIdx == iCount ) { return; } iCount++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } UInt uiArrayAddr = iCount; UInt uiCutoff = uiArrayAddr; if ( getSlice()->isInterB() ) { static const UInt NUM_PRIORITY_LIST=12; static const UInt uiPriorityList0[NUM_PRIORITY_LIST] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3}; static const UInt uiPriorityList1[NUM_PRIORITY_LIST] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2}; for (Int idx=0; idxgetMaxNumMergeCand(); idx++) { assert(idxgetRefPOC( REF_PIC_LIST_0, pcMvFieldNeighbours[(uiArrayAddr<<1)].getRefIdx() ); Int iRefPOCL1 = m_pcSlice->getRefPOC( REF_PIC_LIST_1, pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getRefIdx() ); if (iRefPOCL0 == iRefPOCL1 && pcMvFieldNeighbours[(uiArrayAddr<<1)].getMv() == pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getMv()) { abCandIsInter[uiArrayAddr] = false; } else { uiArrayAddr++; } } } } // early termination if (uiArrayAddr == getSlice()->getMaxNumMergeCand()) { return; } Int iNumRefIdx = (getSlice()->isInterB()) ? min(m_pcSlice->getNumRefIdx(REF_PIC_LIST_0), m_pcSlice->getNumRefIdx(REF_PIC_LIST_1)) : m_pcSlice->getNumRefIdx(REF_PIC_LIST_0); Int r = 0; Int refcnt = 0; while (uiArrayAddr < getSlice()->getMaxNumMergeCand()) { abCandIsInter[uiArrayAddr] = true; puhInterDirNeighbours[uiArrayAddr] = 1; pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( TComMv(0, 0), r); if ( getSlice()->isInterB() ) { puhInterDirNeighbours[uiArrayAddr] = 3; pcMvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(TComMv(0, 0), r); } uiArrayAddr++; if ( refcnt == iNumRefIdx - 1 ) { r = 0; } else { ++r; ++refcnt; } } numValidMergeCand = uiArrayAddr; } /** Check whether the current PU and a spatial neighboring PU are in a same ME region. * \param xN, yN location of the upper-left corner pixel of a neighboring PU * \param xP, yP location of the upper-left corner pixel of the current PU */ Bool TComDataCU::isDiffMER(Int xN, Int yN, Int xP, Int yP) const { UInt plevel = this->getSlice()->getPPS()->getLog2ParallelMergeLevelMinus2() + 2; if ((xN>>plevel)!= (xP>>plevel)) { return true; } if ((yN>>plevel)!= (yP>>plevel)) { return true; } return false; } /** Calculate the location of upper-left corner pixel and size of the current PU. * \param partIdx PU index within a CU * \param xP, yP location of the upper-left corner pixel of the current PU * \param nPSW, nPSH size of the current PU */ Void TComDataCU::getPartPosition( UInt partIdx, Int& xP, Int& yP, Int& nPSW, Int& nPSH) const { UInt col = m_uiCUPelX; UInt row = m_uiCUPelY; switch ( m_pePartSize[0] ) { case SIZE_2NxN: nPSW = getWidth(0); nPSH = getHeight(0) >> 1; xP = col; yP = (partIdx ==0)? row: row + nPSH; break; case SIZE_Nx2N: nPSW = getWidth(0) >> 1; nPSH = getHeight(0); xP = (partIdx ==0)? col: col + nPSW; yP = row; break; case SIZE_NxN: nPSW = getWidth(0) >> 1; nPSH = getHeight(0) >> 1; xP = col + (partIdx&0x1)*nPSW; yP = row + (partIdx>>1)*nPSH; break; case SIZE_2NxnU: nPSW = getWidth(0); nPSH = ( partIdx == 0 ) ? getHeight(0) >> 2 : ( getHeight(0) >> 2 ) + ( getHeight(0) >> 1 ); xP = col; yP = (partIdx ==0)? row: row + getHeight(0) - nPSH; break; case SIZE_2NxnD: nPSW = getWidth(0); nPSH = ( partIdx == 0 ) ? ( getHeight(0) >> 2 ) + ( getHeight(0) >> 1 ) : getHeight(0) >> 2; xP = col; yP = (partIdx ==0)? row: row + getHeight(0) - nPSH; break; case SIZE_nLx2N: nPSW = ( partIdx == 0 ) ? getWidth(0) >> 2 : ( getWidth(0) >> 2 ) + ( getWidth(0) >> 1 ); nPSH = getHeight(0); xP = (partIdx ==0)? col: col + getWidth(0) - nPSW; yP = row; break; case SIZE_nRx2N: nPSW = ( partIdx == 0 ) ? ( getWidth(0) >> 2 ) + ( getWidth(0) >> 1 ) : getWidth(0) >> 2; nPSH = getHeight(0); xP = (partIdx ==0)? col: col + getWidth(0) - nPSW; yP = row; break; default: assert ( m_pePartSize[0] == SIZE_2Nx2N ); nPSW = getWidth(0); nPSH = getHeight(0); xP = col ; yP = row ; break; } } /** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates") * \param uiPartIdx * \param uiPartAddr * \param eRefPicList * \param iRefIdx * \param pInfo */ Void TComDataCU::fillMvpCand ( const UInt partIdx, const UInt partAddr, const RefPicList eRefPicList, const Int refIdx, AMVPInfo* pInfo ) const { pInfo->iN = 0; if (refIdx < 0) { #if MCTS_ENC_CHECK pInfo->numSpatialMVPCandidates = 0; #endif return; } //-- Get Spatial MV UInt partIdxLT, partIdxRT, partIdxLB; deriveLeftRightTopIdx( partIdx, partIdxLT, partIdxRT ); deriveLeftBottomIdx( partIdx, partIdxLB ); Bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1). { UInt idx; const TComDataCU* tmpCU = getPUBelowLeft(idx, partIdxLB); isScaledFlagLX = (tmpCU != NULL) && (tmpCU->isInter(idx)); if (!isScaledFlagLX) { tmpCU = getPULeft(idx, partIdxLB); isScaledFlagLX = (tmpCU != NULL) && (tmpCU->isInter(idx)); } } // Left predictor search if (isScaledFlagLX) { Bool bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLB, MD_BELOW_LEFT); if (!bAdded) { bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLB, MD_LEFT ); if(!bAdded) { bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLB, MD_BELOW_LEFT); if (!bAdded) { xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLB, MD_LEFT ); } } } } // Above predictor search { Bool bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE_RIGHT); if (!bAdded) { bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE); if(!bAdded) { xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLT, MD_ABOVE_LEFT); } } } if(!isScaledFlagLX) { Bool bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE_RIGHT); if (!bAdded) { bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE); if(!bAdded) { xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLT, MD_ABOVE_LEFT); } } } if ( pInfo->iN == 2 ) { if ( pInfo->m_acMvCand[ 0 ] == pInfo->m_acMvCand[ 1 ] ) { pInfo->iN = 1; } } #if MCTS_ENC_CHECK pInfo->numSpatialMVPCandidates = pInfo->iN; #endif if (pInfo->iN < AMVP_MAX_NUM_CANDS && getSlice()->getEnableTMVPFlag() ) { // Get Temporal Motion Predictor const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); const UInt numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight(); const Int refIdx_Col = refIdx; TComMv cColMv; UInt partIdxRB; UInt absPartIdx; deriveRightBottomIdx( partIdx, partIdxRB ); UInt absPartAddr = m_absZIdxInCtu + partAddr; //---- co-located RightBottom Temporal Predictor (H) ---// absPartIdx = g_auiZscanToRaster[partIdxRB]; Int ctuRsAddr = -1; if ( ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[absPartIdx] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () ) // image boundary check && ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[absPartIdx] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) ) { if ( ( absPartIdx % numPartInCtuWidth < numPartInCtuWidth - 1 ) && // is not at the last column of CTU ( absPartIdx / numPartInCtuWidth < numPartInCtuHeight - 1 ) ) // is not at the last row of CTU { absPartAddr = g_auiRasterToZscan[ absPartIdx + numPartInCtuWidth + 1 ]; ctuRsAddr = getCtuRsAddr(); } else if ( absPartIdx % numPartInCtuWidth < numPartInCtuWidth - 1 ) // is not at the last column of CTU But is last row of CTU { absPartAddr = g_auiRasterToZscan[ (absPartIdx + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ]; } else if ( absPartIdx / numPartInCtuWidth < numPartInCtuHeight - 1 ) // is not at the last row of CTU But is last column of CTU { absPartAddr = g_auiRasterToZscan[ absPartIdx + 1 ]; ctuRsAddr = getCtuRsAddr() + 1; } else //is the right bottom corner of CTU { absPartAddr = 0; } } if ( ctuRsAddr >= 0 && xGetColMVP( eRefPicList, ctuRsAddr, absPartAddr, cColMv, refIdx_Col ) ) { pInfo->m_acMvCand[pInfo->iN++] = cColMv; } else { UInt uiPartIdxCenter; xDeriveCenterIdx( partIdx, uiPartIdxCenter ); if (xGetColMVP( eRefPicList, getCtuRsAddr(), uiPartIdxCenter, cColMv, refIdx_Col )) { pInfo->m_acMvCand[pInfo->iN++] = cColMv; } } //---- co-located RightBottom Temporal Predictor ---// } while (pInfo->iN < AMVP_MAX_NUM_CANDS) { pInfo->m_acMvCand[pInfo->iN].set(0,0); pInfo->iN++; } return ; } Bool TComDataCU::isBipredRestriction(UInt puIdx) const { Int width = 0; Int height = 0; UInt partAddr; getPartIndexAndSize( puIdx, partAddr, width, height ); if ( getWidth(0) == 8 && (width < 8 || height < 8) ) { return true; } return false; } Void TComDataCU::clipMv (TComMv& rcMv) const { const TComSPS &sps=*(m_pcSlice->getSPS()); Int iMvShift = 2; Int iOffset = 8; Int iHorMax = ( sps.getPicWidthInLumaSamples() + iOffset - (Int)m_uiCUPelX - 1 ) << iMvShift; Int iHorMin = ( -(Int)sps.getMaxCUWidth() - iOffset - (Int)m_uiCUPelX + 1 ) << iMvShift; Int iVerMax = ( sps.getPicHeightInLumaSamples() + iOffset - (Int)m_uiCUPelY - 1 ) << iMvShift; Int iVerMin = ( -(Int)sps.getMaxCUHeight() - iOffset - (Int)m_uiCUPelY + 1 ) << iMvShift; rcMv.setHor( min (iHorMax, max (iHorMin, rcMv.getHor())) ); rcMv.setVer( min (iVerMax, max (iVerMin, rcMv.getVer())) ); } UInt TComDataCU::getIntraSizeIdx(UInt uiAbsPartIdx) const { UInt uiShift = ( m_pePartSize[uiAbsPartIdx]==SIZE_NxN ? 1 : 0 ); UChar uiWidth = m_puhWidth[uiAbsPartIdx]>>uiShift; UInt uiCnt = 0; while( uiWidth ) { uiCnt++; uiWidth>>=1; } uiCnt-=2; return uiCnt > 6 ? 6 : uiCnt; } Void TComDataCU::clearCbf( UInt uiIdx, ComponentID compID, UInt uiNumParts ) { memset( &m_puhCbf[compID][uiIdx], 0, sizeof(UChar)*uiNumParts); } /** Set a I_PCM flag for all sub-partitions of a partition. * \param bIpcmFlag I_PCM flag * \param uiAbsPartIdx patition index * \param uiDepth CU depth * \returns Void */ Void TComDataCU::setIPCMFlagSubParts (Bool bIpcmFlag, UInt uiAbsPartIdx, UInt uiDepth) { UInt uiCurrPartNumb = m_pcPic->getNumPartitionsInCtu() >> (uiDepth << 1); memset(m_pbIPCMFlag + uiAbsPartIdx, bIpcmFlag, sizeof(Bool)*uiCurrPartNumb ); } /** Test whether the block at uiPartIdx is skipped. * \param uiPartIdx Partition index * \returns true if the current the block is skipped */ Bool TComDataCU::isSkipped( UInt uiPartIdx ) const { return ( getSkipFlag( uiPartIdx ) ); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Bool TComDataCU::xAddMVPCandUnscaled( AMVPInfo &info, const RefPicList eRefPicList, const Int iRefIdx, const UInt uiPartUnitIdx, const MVP_DIR eDir ) const { const TComDataCU* neibCU = NULL; UInt neibPUPartIdx; switch( eDir ) { case MD_LEFT: { neibCU = getPULeft(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE: { neibCU = getPUAbove(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE_RIGHT: { neibCU = getPUAboveRight(neibPUPartIdx, uiPartUnitIdx); break; } case MD_BELOW_LEFT: { neibCU = getPUBelowLeft(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE_LEFT: { neibCU = getPUAboveLeft(neibPUPartIdx, uiPartUnitIdx); break; } default: { break; } } if ( neibCU == NULL ) { return false; } const Int currRefPOC = m_pcSlice->getRefPic( eRefPicList, iRefIdx)->getPOC(); const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0; for(Int predictorSource=0; predictorSource<2; predictorSource++) // examine the indicated reference picture list, then if not available, examine the other list. { const RefPicList eRefPicListIndex = (predictorSource==0) ? eRefPicList : eRefPicList2nd; const Int neibRefIdx = neibCU->getCUMvField(eRefPicListIndex)->getRefIdx(neibPUPartIdx); if ( neibRefIdx >= 0 && currRefPOC == neibCU->getSlice()->getRefPOC( eRefPicListIndex, neibRefIdx )) { info.m_acMvCand[info.iN++] = neibCU->getCUMvField(eRefPicListIndex)->getMv(neibPUPartIdx); return true; } } return false; } /** * \param pInfo * \param eRefPicList * \param iRefIdx * \param uiPartUnitIdx * \param eDir * \returns Bool */ Bool TComDataCU::xAddMVPCandWithScaling( AMVPInfo &info, const RefPicList eRefPicList, const Int iRefIdx, const UInt uiPartUnitIdx, const MVP_DIR eDir ) const { const TComDataCU* neibCU = NULL; UInt neibPUPartIdx; switch( eDir ) { case MD_LEFT: { neibCU = getPULeft(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE: { neibCU = getPUAbove(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE_RIGHT: { neibCU = getPUAboveRight(neibPUPartIdx, uiPartUnitIdx); break; } case MD_BELOW_LEFT: { neibCU = getPUBelowLeft(neibPUPartIdx, uiPartUnitIdx); break; } case MD_ABOVE_LEFT: { neibCU = getPUAboveLeft(neibPUPartIdx, uiPartUnitIdx); break; } default: { break; } } if ( neibCU == NULL ) { return false; } const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0; const Int currPOC = m_pcSlice->getPOC(); const Int currRefPOC = m_pcSlice->getRefPic( eRefPicList, iRefIdx)->getPOC(); const Bool bIsCurrRefLongTerm = m_pcSlice->getRefPic( eRefPicList, iRefIdx)->getIsLongTerm(); const Int neibPOC = currPOC; for(Int predictorSource=0; predictorSource<2; predictorSource++) // examine the indicated reference picture list, then if not available, examine the other list. { const RefPicList eRefPicListIndex = (predictorSource==0) ? eRefPicList : eRefPicList2nd; const Int neibRefIdx = neibCU->getCUMvField(eRefPicListIndex)->getRefIdx(neibPUPartIdx); if( neibRefIdx >= 0) { const Bool bIsNeibRefLongTerm = neibCU->getSlice()->getRefPic( eRefPicListIndex, neibRefIdx )->getIsLongTerm(); if ( bIsCurrRefLongTerm == bIsNeibRefLongTerm ) { const TComMv &cMvPred = neibCU->getCUMvField(eRefPicListIndex)->getMv(neibPUPartIdx); TComMv rcMv; if ( bIsCurrRefLongTerm /* || bIsNeibRefLongTerm*/ ) { rcMv = cMvPred; } else { const Int neibRefPOC = neibCU->getSlice()->getRefPOC( eRefPicListIndex, neibRefIdx ); const Int scale = xGetDistScaleFactor( currPOC, currRefPOC, neibPOC, neibRefPOC ); if ( scale == 4096 ) { rcMv = cMvPred; } else { rcMv = cMvPred.scaleMv( scale ); } } info.m_acMvCand[info.iN++] = rcMv; return true; } } } return false; } Bool TComDataCU::xGetColMVP( const RefPicList eRefPicList, const Int ctuRsAddr, const Int partUnitIdx, TComMv& rcMv, const Int refIdx ) const { const UInt absPartAddr = partUnitIdx; // use coldir. const TComPic * const pColPic = getSlice()->getRefPic( RefPicList(getSlice()->isInterB() ? 1-getSlice()->getColFromL0Flag() : 0), getSlice()->getColRefIdx()); #if REDUCED_ENCODER_MEMORY if (!pColPic->getPicSym()->hasDPBPerCtuData()) { return false; } const TComPicSym::DPBPerCtuData * const pColDpbCtu = &(pColPic->getPicSym()->getDPBPerCtuData(ctuRsAddr)); const TComSlice * const pColSlice = pColDpbCtu->getSlice(); if(pColDpbCtu->getPartitionSize(partUnitIdx)==NUMBER_OF_PART_SIZES) #else const TComDataCU * const pColCtu = pColPic->getCtu( ctuRsAddr ); if(pColCtu->getPic()==0 || pColCtu->getPartitionSize(partUnitIdx)==NUMBER_OF_PART_SIZES) #endif { return false; } #if REDUCED_ENCODER_MEMORY if (!pColDpbCtu->isInter(absPartAddr)) #else if (!pColCtu->isInter(absPartAddr)) #endif { return false; } RefPicList eColRefPicList = getSlice()->getCheckLDC() ? eRefPicList : RefPicList(getSlice()->getColFromL0Flag()); #if REDUCED_ENCODER_MEMORY Int iColRefIdx = pColDpbCtu->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(absPartAddr); #else Int iColRefIdx = pColCtu->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(absPartAddr); #endif if (iColRefIdx < 0 ) { eColRefPicList = RefPicList(1 - eColRefPicList); #if REDUCED_ENCODER_MEMORY iColRefIdx = pColDpbCtu->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(absPartAddr); #else iColRefIdx = pColCtu->getCUMvField(RefPicList(eColRefPicList))->getRefIdx(absPartAddr); #endif if (iColRefIdx < 0 ) { return false; } } const Bool bIsCurrRefLongTerm = m_pcSlice->getRefPic(eRefPicList, refIdx)->getIsLongTerm(); #if REDUCED_ENCODER_MEMORY const Bool bIsColRefLongTerm = pColSlice->getIsUsedAsLongTerm(eColRefPicList, iColRefIdx); #else const Bool bIsColRefLongTerm = pColCtu->getSlice()->getIsUsedAsLongTerm(eColRefPicList, iColRefIdx); #endif if ( bIsCurrRefLongTerm != bIsColRefLongTerm ) { return false; } // Scale the vector. #if REDUCED_ENCODER_MEMORY const TComMv &cColMv = pColDpbCtu->getCUMvField(eColRefPicList)->getMv(absPartAddr); #else const TComMv &cColMv = pColCtu->getCUMvField(eColRefPicList)->getMv(absPartAddr); #endif if ( bIsCurrRefLongTerm /*|| bIsColRefLongTerm*/ ) { rcMv = cColMv; } else { const Int currPOC = m_pcSlice->getPOC(); #if REDUCED_ENCODER_MEMORY const Int colPOC = pColSlice->getPOC(); const Int colRefPOC = pColSlice->getRefPOC(eColRefPicList, iColRefIdx); #else const Int colPOC = pColCtu->getSlice()->getPOC(); const Int colRefPOC = pColCtu->getSlice()->getRefPOC(eColRefPicList, iColRefIdx); #endif const Int currRefPOC = m_pcSlice->getRefPic(eRefPicList, refIdx)->getPOC(); const Int scale = xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC); if ( scale == 4096 ) { rcMv = cColMv; } else { rcMv = cColMv.scaleMv( scale ); } } return true; } // Static member Int TComDataCU::xGetDistScaleFactor(Int iCurrPOC, Int iCurrRefPOC, Int iColPOC, Int iColRefPOC) { Int iDiffPocD = iColPOC - iColRefPOC; Int iDiffPocB = iCurrPOC - iCurrRefPOC; if( iDiffPocD == iDiffPocB ) { return 4096; } else { Int iTDB = Clip3( -128, 127, iDiffPocB ); Int iTDD = Clip3( -128, 127, iDiffPocD ); Int iX = (0x4000 + abs(iTDD/2)) / iTDD; Int iScale = Clip3( -4096, 4095, (iTDB * iX + 32) >> 6 ); return iScale; } } Void TComDataCU::xDeriveCenterIdx( UInt uiPartIdx, UInt& ruiPartIdxCenter ) const { UInt uiPartAddr; Int iPartWidth; Int iPartHeight; getPartIndexAndSize( uiPartIdx, uiPartAddr, iPartWidth, iPartHeight); ruiPartIdxCenter = m_absZIdxInCtu+uiPartAddr; // partition origin. ruiPartIdxCenter = g_auiRasterToZscan[ g_auiZscanToRaster[ ruiPartIdxCenter ] + ( iPartHeight/m_pcPic->getMinCUHeight() )/2*m_pcPic->getNumPartInCtuWidth() + ( iPartWidth/m_pcPic->getMinCUWidth() )/2]; } Void TComDataCU::compressMV() { #if REDUCED_ENCODER_MEMORY const Int scaleFactor = std::max(1,4 * AMVP_DECIMATION_FACTOR / m_unitSize); TComPicSym &picSym=*(getPic()->getPicSym()); TComPicSym::DPBPerCtuData &dpbForCtu=picSym.getDPBPerCtuData(getCtuRsAddr()); for(UInt i=0; i 0) { for(UInt i=0; igetChromaFormat(); const UInt maximumWidth = MDCS_MAXIMUM_WIDTH >> getComponentScaleX(compID, format); const UInt maximumHeight = MDCS_MAXIMUM_HEIGHT >> getComponentScaleY(compID, format); if ((uiWidth > maximumWidth) || (uiHeight > maximumHeight)) { return SCAN_DIAG; } //------------------------------------------------ //otherwise, select the appropriate mode UInt uiDirMode = getIntraDir(toChannelType(compID), uiAbsPartIdx); if (uiDirMode==DM_CHROMA_IDX) { const TComSPS *sps=getSlice()->getSPS(); const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())); uiDirMode = getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, getPic()->getChromaFormat(), partsPerMinCU)); } if (isChroma(compID) && (format == CHROMA_422)) { uiDirMode = g_chroma422IntraAngleMappingTable[uiDirMode]; } //------------------ if (abs((Int)uiDirMode - VER_IDX) <= MDCS_ANGLE_LIMIT) { return SCAN_HOR; } else if (abs((Int)uiDirMode - HOR_IDX) <= MDCS_ANGLE_LIMIT) { return SCAN_VER; } else { return SCAN_DIAG; } } #if MCTS_ENC_CHECK Bool TComDataCU::isLastColumnCTUInTile() const { UInt currentTileIdx = this->getPic()->getPicSym()->getTileIdxMap(this->getCtuRsAddr()); TComTile *pCurrentTile = m_pcPic->getPicSym()->getTComTile(currentTileIdx); UInt frameWidthInCtus = m_pcPic->getPicSym()->getFrameWidthInCtus(); UInt rightEdgeCTUPosInCurrentTile = pCurrentTile->getRightEdgePosInCtus(); UInt ctuXPosInCtus = this->getCtuRsAddr() % frameWidthInCtus; return (rightEdgeCTUPosInCurrentTile == ctuXPosInCtus); } #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/TComDataCU.h000066400000000000000000001216051442026013100203140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComDataCU.h \brief CU data structure (header) \todo not all entities are documented */ #ifndef __TCOMDATACU__ #define __TCOMDATACU__ #include #include // Include files #include "CommonDef.h" #include "TComMotionInfo.h" #include "TComSlice.h" #include "TComRdCost.h" #include "TComPattern.h" //! \ingroup TLibCommon //! \{ class TComTU; // forward declaration static const UInt NUM_MOST_PROBABLE_MODES=3; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// CU data structure class class TComDataCU { private: // ------------------------------------------------------------------------------------------------------------------- // class pointers // ------------------------------------------------------------------------------------------------------------------- TComPic* m_pcPic; ///< picture class pointer TComSlice* m_pcSlice; ///< slice header pointer // ------------------------------------------------------------------------------------------------------------------- // CU description // ------------------------------------------------------------------------------------------------------------------- UInt m_ctuRsAddr; ///< CTU (also known as LCU) address in a slice (Raster-scan address, as opposed to tile-scan/encoding order). UInt m_absZIdxInCtu; ///< absolute address in a CTU. It's Z scan order UInt m_uiCUPelX; ///< CU position in a pixel (X) UInt m_uiCUPelY; ///< CU position in a pixel (Y) UInt m_uiNumPartition; ///< total number of minimum partitions in a CU UChar* m_puhWidth; ///< array of widths UChar* m_puhHeight; ///< array of heights UChar* m_puhDepth; ///< array of depths Int m_unitSize; ///< size of a "minimum partition" // ------------------------------------------------------------------------------------------------------------------- // CU data // ------------------------------------------------------------------------------------------------------------------- Bool* m_skipFlag; ///< array of skip flags SChar* m_pePartSize; ///< array of partition sizes SChar* m_pePredMode; ///< array of prediction modes SChar* m_crossComponentPredictionAlpha[MAX_NUM_COMPONENT]; ///< array of cross-component prediction alpha values Bool* m_CUTransquantBypass; ///< array of cu_transquant_bypass flags SChar* m_phQP; ///< array of QP values UChar* m_ChromaQpAdj; ///< array of chroma QP adjustments (indexed). when value = 0, cu_chroma_qp_offset_flag=0; when value>0, indicates cu_chroma_qp_offset_flag=1 and cu_chroma_qp_offset_idx=value-1 UInt m_codedChromaQpAdj; UChar* m_puhTrIdx; ///< array of transform indices UChar* m_puhTransformSkip[MAX_NUM_COMPONENT]; ///< array of transform skipping flags UChar* m_puhCbf[MAX_NUM_COMPONENT]; ///< array of coded block flags (CBF) TComCUMvField m_acCUMvField[NUM_REF_PIC_LIST_01]; ///< array of motion vectors. TCoeff* m_pcTrCoeff[MAX_NUM_COMPONENT]; ///< array of transform coefficient buffers (0->Y, 1->Cb, 2->Cr) #if ADAPTIVE_QP_SELECTION TCoeff* m_pcArlCoeff[MAX_NUM_COMPONENT]; ///< ARL coefficient buffer (0->Y, 1->Cb, 2->Cr) Bool m_ArlCoeffIsAliasedAllocation; ///< ARL coefficient buffer is an alias of the global buffer and must not be free()'d #endif Pel* m_pcIPCMSample[MAX_NUM_COMPONENT]; ///< PCM sample buffer (0->Y, 1->Cb, 2->Cr) // ------------------------------------------------------------------------------------------------------------------- // neighbour access variables // ------------------------------------------------------------------------------------------------------------------- TComDataCU* m_pCtuAboveLeft; ///< pointer of above-left CTU. TComDataCU* m_pCtuAboveRight; ///< pointer of above-right CTU. TComDataCU* m_pCtuAbove; ///< pointer of above CTU. TComDataCU* m_pCtuLeft; ///< pointer of left CTU TComMvField m_cMvFieldA; ///< motion vector of position A TComMvField m_cMvFieldB; ///< motion vector of position B TComMvField m_cMvFieldC; ///< motion vector of position C TComMv m_cMvPred; ///< motion vector predictor // ------------------------------------------------------------------------------------------------------------------- // coding tool information // ------------------------------------------------------------------------------------------------------------------- Bool* m_pbMergeFlag; ///< array of merge flags UChar* m_puhMergeIndex; ///< array of merge candidate indices #if AMP_MRG Bool m_bIsMergeAMP; #endif UChar* m_puhIntraDir[MAX_NUM_CHANNEL_TYPE]; UChar* m_puhInterDir; ///< array of inter directions SChar* m_apiMVPIdx[NUM_REF_PIC_LIST_01]; ///< array of motion vector predictor candidates SChar* m_apiMVPNum[NUM_REF_PIC_LIST_01]; ///< array of number of possible motion vectors predictors Bool* m_pbIPCMFlag; ///< array of intra_pcm flags #if MCTS_ENC_CHECK Bool m_tMctsMvpIsValid; #endif // ------------------------------------------------------------------------------------------------------------------- // misc. variables // ------------------------------------------------------------------------------------------------------------------- Bool m_bDecSubCu; ///< indicates decoder-mode Double m_dTotalCost; ///< sum of partition RD costs Distortion m_uiTotalDistortion; ///< sum of partition distortion UInt m_uiTotalBits; ///< sum of partition bits UInt m_uiTotalBins; ///< sum of partition bins SChar m_codedQP; UChar* m_explicitRdpcmMode[MAX_NUM_COMPONENT]; ///< Stores the explicit RDPCM mode for all TUs belonging to this CU protected: /// adds a single possible motion vector predictor candidate Bool xAddMVPCandUnscaled ( AMVPInfo &info, const RefPicList eRefPicList, const Int iRefIdx, const UInt uiPartUnitIdx, const MVP_DIR eDir ) const; Bool xAddMVPCandWithScaling ( AMVPInfo &info, const RefPicList eRefPicList, const Int iRefIdx, const UInt uiPartUnitIdx, const MVP_DIR eDir ) const; Void deriveRightBottomIdx ( UInt uiPartIdx, UInt& ruiPartIdxRB ) const; Bool xGetColMVP ( const RefPicList eRefPicList, const Int ctuRsAddr, const Int partUnitIdx, TComMv& rcMv, const Int refIdx ) const; /// compute scaling factor from POC difference static Int xGetDistScaleFactor ( Int iCurrPOC, Int iCurrRefPOC, Int iColPOC, Int iColRefPOC ); Void xDeriveCenterIdx ( UInt uiPartIdx, UInt& ruiPartIdxCenter ) const; public: TComDataCU(); virtual ~TComDataCU(); // ------------------------------------------------------------------------------------------------------------------- // create / destroy / initialize / copy // ------------------------------------------------------------------------------------------------------------------- Void create ( ChromaFormat chromaFormatIDC, UInt uiNumPartition, UInt uiWidth, UInt uiHeight, Bool bDecSubCu, Int unitSize #if ADAPTIVE_QP_SELECTION , TCoeff *pParentARLBuffer = 0 #endif ); Void destroy ( ); Void initCtu ( TComPic* pcPic, UInt ctuRsAddr ); Void initEstData ( const UInt uiDepth, const Int qp, const Bool bTransquantBypass ); Void initSubCU ( TComDataCU* pcCU, UInt uiPartUnitIdx, UInt uiDepth, Int qp ); Void setOutsideCUPart ( UInt uiAbsPartIdx, UInt uiDepth ); Void copySubCU ( TComDataCU* pcCU, UInt uiPartUnitIdx ); Void copyInterPredInfoFrom ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefPicList ); Void copyPartFrom ( TComDataCU* pcCU, UInt uiPartUnitIdx, UInt uiDepth ); Void copyToPic ( UChar uiDepth ); // ------------------------------------------------------------------------------------------------------------------- // member functions for CU description // ------------------------------------------------------------------------------------------------------------------- TComPic* getPic ( ) { return m_pcPic; } const TComPic* getPic ( ) const { return m_pcPic; } TComSlice* getSlice ( ) { return m_pcSlice; } const TComSlice* getSlice ( ) const { return m_pcSlice; } UInt& getCtuRsAddr ( ) { return m_ctuRsAddr; } UInt getCtuRsAddr ( ) const { return m_ctuRsAddr; } UInt getZorderIdxInCtu ( ) const { return m_absZIdxInCtu; } UInt getCUPelX ( ) const { return m_uiCUPelX; } UInt getCUPelY ( ) const { return m_uiCUPelY; } UChar* getDepth ( ) { return m_puhDepth; } UChar getDepth ( UInt uiIdx ) const { return m_puhDepth[uiIdx]; } Void setDepth ( UInt uiIdx, UChar uh ) { m_puhDepth[uiIdx] = uh; } Void setDepthSubParts ( UInt uiDepth, UInt uiAbsPartIdx ); #if MCTS_ENC_CHECK Void setTMctsMvpIsValid(Bool b) { m_tMctsMvpIsValid = b; } Bool getTMctsMvpIsValid() { return m_tMctsMvpIsValid; } Bool isLastColumnCTUInTile() const; #endif // ------------------------------------------------------------------------------------------------------------------- // member functions for CU data // ------------------------------------------------------------------------------------------------------------------- SChar* getPartitionSize ( ) { return m_pePartSize; } PartSize getPartitionSize ( UInt uiIdx ) const { return static_cast( m_pePartSize[uiIdx] ); } Void setPartitionSize ( UInt uiIdx, PartSize uh ) { m_pePartSize[uiIdx] = uh; } Void setPartSizeSubParts ( PartSize eMode, UInt uiAbsPartIdx, UInt uiDepth ); Void setCUTransquantBypassSubParts ( Bool flag, UInt uiAbsPartIdx, UInt uiDepth ); Bool* getSkipFlag ( ) { return m_skipFlag; } Bool getSkipFlag ( UInt idx ) const { return m_skipFlag[idx]; } Void setSkipFlag ( UInt idx, Bool skip ) { m_skipFlag[idx] = skip; } Void setSkipFlagSubParts ( Bool skip, UInt absPartIdx, UInt depth ); SChar* getPredictionMode ( ) { return m_pePredMode; } PredMode getPredictionMode ( UInt uiIdx ) const { return static_cast( m_pePredMode[uiIdx] ); } Void setPredictionMode ( UInt uiIdx, PredMode uh ) { m_pePredMode[uiIdx] = uh; } Void setPredModeSubParts ( PredMode eMode, UInt uiAbsPartIdx, UInt uiDepth ); SChar* getCrossComponentPredictionAlpha( ComponentID compID ) { return m_crossComponentPredictionAlpha[compID]; } SChar getCrossComponentPredictionAlpha( UInt uiIdx, ComponentID compID ) { return m_crossComponentPredictionAlpha[compID][uiIdx]; } Bool* getCUTransquantBypass ( ) { return m_CUTransquantBypass; } Bool getCUTransquantBypass ( UInt uiIdx ) const { return m_CUTransquantBypass[uiIdx]; } UChar* getWidth ( ) { return m_puhWidth; } UChar getWidth ( UInt uiIdx ) const { return m_puhWidth[uiIdx]; } Void setWidth ( UInt uiIdx, UChar uh ) { m_puhWidth[uiIdx] = uh; } UChar* getHeight ( ) { return m_puhHeight; } UChar getHeight ( UInt uiIdx ) const { return m_puhHeight[uiIdx]; } Void setHeight ( UInt uiIdx, UChar uh ) { m_puhHeight[uiIdx] = uh; } Void setSizeSubParts ( UInt uiWidth, UInt uiHeight, UInt uiAbsPartIdx, UInt uiDepth ); SChar* getQP ( ) { return m_phQP; } SChar getQP ( UInt uiIdx ) const { return m_phQP[uiIdx]; } Void setQP ( UInt uiIdx, SChar value ) { m_phQP[uiIdx] = value; } Void setQPSubParts ( Int qp, UInt uiAbsPartIdx, UInt uiDepth ); Int getLastValidPartIdx ( Int iAbsPartIdx ) const; SChar getLastCodedQP ( UInt uiAbsPartIdx ) const; Void setQPSubCUs ( Int qp, UInt absPartIdx, UInt depth, Bool &foundNonZeroCbf ); Void setCodedQP ( SChar qp ) { m_codedQP = qp; } SChar getCodedQP ( ) const { return m_codedQP; } UChar* getChromaQpAdj ( ) { return m_ChromaQpAdj; } ///< array of chroma QP adjustments (indexed). when value = 0, cu_chroma_qp_offset_flag=0; when value>0, indicates cu_chroma_qp_offset_flag=1 and cu_chroma_qp_offset_idx=value-1 UChar getChromaQpAdj ( Int idx ) const { return m_ChromaQpAdj[idx]; } ///< When value = 0, cu_chroma_qp_offset_flag=0; when value>0, indicates cu_chroma_qp_offset_flag=1 and cu_chroma_qp_offset_idx=value-1 Void setChromaQpAdj ( Int idx, UChar val ) { m_ChromaQpAdj[idx] = val; } ///< When val = 0, cu_chroma_qp_offset_flag=0; when val>0, indicates cu_chroma_qp_offset_flag=1 and cu_chroma_qp_offset_idx=val-1 Void setChromaQpAdjSubParts ( UChar val, Int absPartIdx, Int depth ); Void setCodedChromaQpAdj ( SChar qp ) { m_codedChromaQpAdj = qp; } SChar getCodedChromaQpAdj ( ) const { return m_codedChromaQpAdj; } Bool isLosslessCoded ( UInt absPartIdx ) const; UChar* getTransformIdx ( ) { return m_puhTrIdx; } UChar getTransformIdx ( UInt uiIdx ) const { return m_puhTrIdx[uiIdx]; } Void setTrIdxSubParts ( UInt uiTrIdx, UInt uiAbsPartIdx, UInt uiDepth ); UChar* getTransformSkip ( ComponentID compID ) { return m_puhTransformSkip[compID]; } UChar getTransformSkip ( UInt uiIdx, ComponentID compID ) const { return m_puhTransformSkip[compID][uiIdx]; } Void setTransformSkipSubParts ( UInt useTransformSkip, ComponentID compID, UInt uiAbsPartIdx, UInt uiDepth ); Void setTransformSkipSubParts ( const UInt useTransformSkip[MAX_NUM_COMPONENT], UInt uiAbsPartIdx, UInt uiDepth ); UChar* getExplicitRdpcmMode ( ComponentID component ) { return m_explicitRdpcmMode[component]; } UChar getExplicitRdpcmMode ( ComponentID component, UInt partIdx ) const { return m_explicitRdpcmMode[component][partIdx]; } Void setExplicitRdpcmModePartRange ( UInt rdpcmMode, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ); Bool isRDPCMEnabled ( UInt uiAbsPartIdx ) const { return getSlice()->getSPS()->getSpsRangeExtension().getRdpcmEnabledFlag(isIntra(uiAbsPartIdx) ? RDPCM_SIGNAL_IMPLICIT : RDPCM_SIGNAL_EXPLICIT); } Void setCrossComponentPredictionAlphaPartRange ( SChar alphaValue, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ); Void setTransformSkipPartRange ( UInt useTransformSkip, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ); UInt getQuadtreeTULog2MinSizeInCU ( UInt uiIdx ) const; TComCUMvField* getCUMvField ( RefPicList e ) { return &m_acCUMvField[e]; } const TComCUMvField* getCUMvField ( RefPicList e ) const { return &m_acCUMvField[e]; } TCoeff* getCoeff ( ComponentID component ) { return m_pcTrCoeff[component]; } #if ADAPTIVE_QP_SELECTION TCoeff* getArlCoeff ( ComponentID component ) { return m_pcArlCoeff[component]; } #endif Pel* getPCMSample ( ComponentID component ) { return m_pcIPCMSample[component]; } UChar getCbf ( UInt uiIdx, ComponentID eType ) const { return m_puhCbf[eType][uiIdx]; } UChar* getCbf ( ComponentID eType ) { return m_puhCbf[eType]; } UChar getCbf ( UInt uiIdx, ComponentID eType, UInt uiTrDepth ) const { return ( ( getCbf( uiIdx, eType ) >> uiTrDepth ) & 0x1 ); } Void setCbf ( UInt uiIdx, ComponentID eType, UChar uh ) { m_puhCbf[eType][uiIdx] = uh; } Void clearCbf ( UInt uiIdx, ComponentID eType, UInt uiNumParts ); UChar getQtRootCbf ( UInt uiIdx ) const; Void setCbfSubParts ( const UInt uiCbf[MAX_NUM_COMPONENT], UInt uiAbsPartIdx, UInt uiDepth ); Void setCbfSubParts ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiDepth ); Void setCbfSubParts ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); Void setCbfPartRange ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ); Void bitwiseOrCbfPartRange ( UInt uiCbf, ComponentID compID, UInt uiAbsPartIdx, UInt uiCoveredPartIdxes ); // ------------------------------------------------------------------------------------------------------------------- // member functions for coding tool information // ------------------------------------------------------------------------------------------------------------------- Bool* getMergeFlag ( ) { return m_pbMergeFlag; } Bool getMergeFlag ( UInt uiIdx ) const { return m_pbMergeFlag[uiIdx]; } Void setMergeFlag ( UInt uiIdx, Bool b ) { m_pbMergeFlag[uiIdx] = b; } Void setMergeFlagSubParts ( Bool bMergeFlag, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); UChar* getMergeIndex ( ) { return m_puhMergeIndex; } UChar getMergeIndex ( UInt uiIdx ) const { return m_puhMergeIndex[uiIdx]; } Void setMergeIndex ( UInt uiIdx, UInt uiMergeIndex ) { m_puhMergeIndex[uiIdx] = uiMergeIndex; } Void setMergeIndexSubParts ( UInt uiMergeIndex, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); template Void setSubPart ( T bParameter, T* pbBaseCtu, UInt uiCUAddr, UInt uiCUDepth, UInt uiPUIdx ); #if AMP_MRG Void setMergeAMP ( Bool b ) { m_bIsMergeAMP = b; } Bool getMergeAMP ( ) const { return m_bIsMergeAMP; } #endif UChar* getIntraDir ( const ChannelType channelType ) const { return m_puhIntraDir[channelType]; } UChar getIntraDir ( const ChannelType channelType, const UInt uiIdx ) const { return m_puhIntraDir[channelType][uiIdx]; } Void setIntraDirSubParts ( const ChannelType channelType, const UInt uiDir, const UInt uiAbsPartIdx, const UInt uiDepth ); UChar* getInterDir ( ) { return m_puhInterDir; } UChar getInterDir ( UInt uiIdx ) const { return m_puhInterDir[uiIdx]; } Void setInterDir ( UInt uiIdx, UChar uh ) { m_puhInterDir[uiIdx] = uh; } Void setInterDirSubParts ( UInt uiDir, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); Bool* getIPCMFlag ( ) { return m_pbIPCMFlag; } Bool getIPCMFlag ( UInt uiIdx ) const { return m_pbIPCMFlag[uiIdx]; } Void setIPCMFlag ( UInt uiIdx, Bool b ) { m_pbIPCMFlag[uiIdx] = b; } Void setIPCMFlagSubParts ( Bool bIpcmFlag, UInt uiAbsPartIdx, UInt uiDepth ); // ------------------------------------------------------------------------------------------------------------------- // member functions for accessing partition information // ------------------------------------------------------------------------------------------------------------------- Void getPartIndexAndSize ( UInt uiPartIdx, UInt& ruiPartAddr, Int& riWidth, Int& riHeight ) const; // This is for use by a leaf/sub CU object only, with no additional AbsPartIdx UChar getNumPartitions ( const UInt uiAbsPartIdx = 0 ) const; Bool isFirstAbsZorderIdxInDepth ( UInt uiAbsPartIdx, UInt uiDepth ) const; // ------------------------------------------------------------------------------------------------------------------- // member functions for motion vector // ------------------------------------------------------------------------------------------------------------------- static Void getMvField ( const TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefPicList, TComMvField& rcMvField ); Void fillMvpCand ( const UInt uiPartIdx, const UInt uiPartAddr, const RefPicList eRefPicList, const Int iRefIdx, AMVPInfo* pInfo ) const; Bool isDiffMER ( Int xN, Int yN, Int xP, Int yP ) const; Void getPartPosition ( UInt partIdx, Int& xP, Int& yP, Int& nPSW, Int& nPSH ) const; Void setMVPIdx ( RefPicList eRefPicList, UInt uiIdx, Int iMVPIdx) { m_apiMVPIdx[eRefPicList][uiIdx] = iMVPIdx; } Int getMVPIdx ( RefPicList eRefPicList, UInt uiIdx) const { return m_apiMVPIdx[eRefPicList][uiIdx]; } SChar* getMVPIdx ( RefPicList eRefPicList ) { return m_apiMVPIdx[eRefPicList]; } Void setMVPNum ( RefPicList eRefPicList, UInt uiIdx, Int iMVPNum ) { m_apiMVPNum[eRefPicList][uiIdx] = iMVPNum; } Int getMVPNum ( RefPicList eRefPicList, UInt uiIdx ) const { return m_apiMVPNum[eRefPicList][uiIdx]; } SChar* getMVPNum ( RefPicList eRefPicList ) { return m_apiMVPNum[eRefPicList]; } Void setMVPIdxSubParts ( Int iMVPIdx, RefPicList eRefPicList, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); Void setMVPNumSubParts ( Int iMVPNum, RefPicList eRefPicList, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ); Void clipMv ( TComMv& rcMv ) const; Void getMvPredLeft ( TComMv& rcMvPred ) const { rcMvPred = m_cMvFieldA.getMv(); } Void getMvPredAbove ( TComMv& rcMvPred ) const { rcMvPred = m_cMvFieldB.getMv(); } Void getMvPredAboveRight ( TComMv& rcMvPred ) const { rcMvPred = m_cMvFieldC.getMv(); } Void compressMV (); // ------------------------------------------------------------------------------------------------------------------- // utility functions for neighbouring information // ------------------------------------------------------------------------------------------------------------------- TComDataCU* getCtuLeft ( ) { return m_pCtuLeft; } TComDataCU* getCtuAbove ( ) { return m_pCtuAbove; } TComDataCU* getCtuAboveLeft ( ) { return m_pCtuAboveLeft; } TComDataCU* getCtuAboveRight ( ) { return m_pCtuAboveRight; } Bool CUIsFromSameSlice ( const TComDataCU *pCU /* Can be NULL */ ) const { return ( pCU!=NULL && pCU->getSlice()->getSliceCurStartCtuTsAddr() == getSlice()->getSliceCurStartCtuTsAddr() ); } Bool CUIsFromSameTile ( const TComDataCU *pCU /* Can be NULL */ ) const; Bool CUIsFromSameSliceAndTile ( const TComDataCU *pCU /* Can be NULL */ ) const; Bool CUIsFromSameSliceTileAndWavefrontRow( const TComDataCU *pCU /* Can be NULL */ ) const; Bool isLastSubCUOfCtu ( const UInt absPartIdx ) const; const TComDataCU* getPULeft ( UInt& uiLPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction=true, Bool bEnforceTileRestriction=true ) const; const TComDataCU* getPUAbove ( UInt& uiAPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction=true, Bool planarAtCTUBoundary = false, Bool bEnforceTileRestriction=true ) const; const TComDataCU* getPUAboveLeft ( UInt& uiALPartUnitIdx, UInt uiCurrPartUnitIdx, Bool bEnforceSliceRestriction=true ) const; const TComDataCU* getQpMinCuLeft ( UInt& uiLPartUnitIdx, UInt uiCurrAbsIdxInCtu ) const; const TComDataCU* getQpMinCuAbove ( UInt& uiAPartUnitIdx, UInt uiCurrAbsIdxInCtu ) const; /// returns CU and part index of the PU above the top row of the current uiCurrPartUnitIdx of the CU, at a horizontal offset (to the right) of uiPartUnitOffset (in parts) const TComDataCU* getPUAboveRight ( UInt& uiARPartUnitIdx, UInt uiCurrPartUnitIdx, UInt uiPartUnitOffset = 1, Bool bEnforceSliceRestriction=true ) const; /// returns CU and part index of the PU left of the lefthand column of the current uiCurrPartUnitIdx of the CU, at a vertical offset (below) of uiPartUnitOffset (in parts) const TComDataCU* getPUBelowLeft ( UInt& uiBLPartUnitIdx, UInt uiCurrPartUnitIdx, UInt uiPartUnitOffset = 1, Bool bEnforceSliceRestriction=true ) const; SChar getRefQP ( UInt uiCurrAbsIdxInCtu ) const; Void deriveLeftRightTopIdx ( UInt uiPartIdx, UInt& ruiPartIdxLT, UInt& ruiPartIdxRT ) const; Void deriveLeftBottomIdx ( UInt uiPartIdx, UInt& ruiPartIdxLB ) const; Bool hasEqualMotion ( UInt uiAbsPartIdx, const TComDataCU* pcCandCU, UInt uiCandAbsPartIdx ) const; #if MCTS_ENC_CHECK Void getInterMergeCandidates ( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, UInt& numSpatialMergeCandidates , Int mrgCandIdx = -1) const; #else Void getInterMergeCandidates ( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx = -1 ) const; #endif Void deriveLeftRightTopIdxGeneral ( UInt uiAbsPartIdx, UInt uiPartIdx, UInt& ruiPartIdxLT, UInt& ruiPartIdxRT ) const; Void deriveLeftBottomIdxGeneral ( UInt uiAbsPartIdx, UInt uiPartIdx, UInt& ruiPartIdxLB ) const; // ------------------------------------------------------------------------------------------------------------------- // member functions for modes // ------------------------------------------------------------------------------------------------------------------- Bool isIntra ( UInt uiPartIdx ) const { return m_pePredMode[ uiPartIdx ] == MODE_INTRA; } Bool isInter ( UInt uiPartIdx ) const { return m_pePredMode[ uiPartIdx ] == MODE_INTER; } Bool isSkipped ( UInt uiPartIdx ) const; ///< returns true, if the partiton is skipped Bool isBipredRestriction ( UInt puIdx ) const; // ------------------------------------------------------------------------------------------------------------------- // member functions for symbol prediction (most probable / mode conversion) // ------------------------------------------------------------------------------------------------------------------- UInt getIntraSizeIdx ( UInt uiAbsPartIdx ) const; Void getAllowedChromaDir ( UInt uiAbsPartIdx, UInt* uiModeList ) const; Void getIntraDirPredictor ( UInt uiAbsPartIdx, Int uiIntraDirPred[NUM_MOST_PROBABLE_MODES], const ComponentID compID, Int* piMode = NULL ) const; // ------------------------------------------------------------------------------------------------------------------- // member functions for SBAC context // ------------------------------------------------------------------------------------------------------------------- UInt getCtxSplitFlag ( UInt uiAbsPartIdx, UInt uiDepth ) const; UInt getCtxQtCbf ( TComTU &rTu, const ChannelType chType ) const; UInt getCtxSkipFlag ( UInt uiAbsPartIdx ) const; UInt getCtxInterDir ( UInt uiAbsPartIdx ) const; UInt& getTotalBins ( ) { return m_uiTotalBins; } // ------------------------------------------------------------------------------------------------------------------- // member functions for RD cost storage // ------------------------------------------------------------------------------------------------------------------- Double& getTotalCost ( ) { return m_dTotalCost; } Distortion& getTotalDistortion ( ) { return m_uiTotalDistortion; } UInt& getTotalBits ( ) { return m_uiTotalBits; } UInt& getTotalNumPart ( ) { return m_uiNumPartition; } UInt getCoefScanIdx ( const UInt uiAbsPartIdx, const UInt uiWidth, const UInt uiHeight, const ComponentID compID ) const ; }; namespace RasterAddress { /** Check whether 2 addresses point to the same column * \param addrA First address in raster scan order * \param addrB Second address in raters scan order * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool isEqualCol( Int addrA, Int addrB, Int numUnitsPerRow ) { // addrA % numUnitsPerRow == addrB % numUnitsPerRow return (( addrA ^ addrB ) & ( numUnitsPerRow - 1 ) ) == 0; } /** Check whether 2 addresses point to the same row * \param addrA First address in raster scan order * \param addrB Second address in raters scan order * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool isEqualRow( Int addrA, Int addrB, Int numUnitsPerRow ) { // addrA / numUnitsPerRow == addrB / numUnitsPerRow return (( addrA ^ addrB ) &~ ( numUnitsPerRow - 1 ) ) == 0; } /** Check whether 2 addresses point to the same row or column * \param addrA First address in raster scan order * \param addrB Second address in raters scan order * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool isEqualRowOrCol( Int addrA, Int addrB, Int numUnitsPerRow ) { return isEqualCol( addrA, addrB, numUnitsPerRow ) | isEqualRow( addrA, addrB, numUnitsPerRow ); } /** Check whether one address points to the first column * \param addr Address in raster scan order * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool isZeroCol( Int addr, Int numUnitsPerRow ) { // addr % numUnitsPerRow == 0 return ( addr & ( numUnitsPerRow - 1 ) ) == 0; } /** Check whether one address points to the first row * \param addr Address in raster scan order * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool isZeroRow( Int addr, Int numUnitsPerRow ) { // addr / numUnitsPerRow == 0 return ( addr &~ ( numUnitsPerRow - 1 ) ) == 0; } /** Check whether one address points to a column whose index is smaller than a given value * \param addr Address in raster scan order * \param val Given column index value * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool lessThanCol( Int addr, Int val, Int numUnitsPerRow ) { // addr % numUnitsPerRow < val return ( addr & ( numUnitsPerRow - 1 ) ) < val; } /** Check whether one address points to a row whose index is smaller than a given value * \param addr Address in raster scan order * \param val Given row index value * \param numUnitsPerRow Number of units in a row * \return Result of test */ static inline Bool lessThanRow( Int addr, Int val, Int numUnitsPerRow ) { // addr / numUnitsPerRow < val return addr < val * numUnitsPerRow; } } //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComInterpolationFilter.cpp000066400000000000000000000533061442026013100235450ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** * \file * \brief Implementation of TComInterpolationFilter class */ // ==================================================================================================================== // Includes // ==================================================================================================================== #include "TComRom.h" #include "TComInterpolationFilter.h" #include #include "TComChromaFormat.h" #if VECTOR_CODING__INTERPOLATION_FILTER && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) #include #endif //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Tables // ==================================================================================================================== const TFilterCoeff TComInterpolationFilter::m_lumaFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_LUMA] = { { 0, 0, 0, 64, 0, 0, 0, 0 }, { -1, 4, -10, 58, 17, -5, 1, 0 }, { -1, 4, -11, 40, 40, -11, 4, -1 }, { 0, 1, -5, 17, 58, -10, 4, -1 } }; const TFilterCoeff TComInterpolationFilter::m_chromaFilter[CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_CHROMA] = { { 0, 64, 0, 0 }, { -2, 58, 10, -2 }, { -4, 54, 16, -2 }, { -6, 46, 28, -4 }, { -4, 36, 36, -4 }, { -4, 28, 46, -6 }, { -2, 16, 54, -4 }, { -2, 10, 58, -2 } }; #if VECTOR_CODING__INTERPOLATION_FILTER && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) inline __m128i simdInterpolateLuma4( Short const *src , Int srcStride , __m128i *mmCoeff , const __m128i & mmOffset , Int shift ) { __m128i sumHi = _mm_setzero_si128(); __m128i sumLo = _mm_setzero_si128(); for( Int n = 0 ; n < 8 ; n++ ) { __m128i mmPix = _mm_loadl_epi64( ( __m128i* )src ); __m128i hi = _mm_mulhi_epi16( mmPix , mmCoeff[n] ); __m128i lo = _mm_mullo_epi16( mmPix , mmCoeff[n] ); sumHi = _mm_add_epi32( sumHi , _mm_unpackhi_epi16( lo , hi ) ); sumLo = _mm_add_epi32( sumLo , _mm_unpacklo_epi16( lo , hi ) ); src += srcStride; } sumHi = _mm_srai_epi32( _mm_add_epi32( sumHi , mmOffset ) , shift ); sumLo = _mm_srai_epi32( _mm_add_epi32( sumLo , mmOffset ) , shift ); return( _mm_packs_epi32( sumLo , sumHi ) ); } inline __m128i simdInterpolateChroma4( Short const *src , Int srcStride , __m128i *mmCoeff , const __m128i & mmOffset , Int shift ) { __m128i sumHi = _mm_setzero_si128(); __m128i sumLo = _mm_setzero_si128(); for( Int n = 0 ; n < 4 ; n++ ) { __m128i mmPix = _mm_loadl_epi64( ( __m128i* )src ); __m128i hi = _mm_mulhi_epi16( mmPix , mmCoeff[n] ); __m128i lo = _mm_mullo_epi16( mmPix , mmCoeff[n] ); sumHi = _mm_add_epi32( sumHi , _mm_unpackhi_epi16( lo , hi ) ); sumLo = _mm_add_epi32( sumLo , _mm_unpacklo_epi16( lo , hi ) ); src += srcStride; } sumHi = _mm_srai_epi32( _mm_add_epi32( sumHi , mmOffset ) , shift ); sumLo = _mm_srai_epi32( _mm_add_epi32( sumLo , mmOffset ) , shift ); return( _mm_packs_epi32( sumLo , sumHi ) ); } inline __m128i simdInterpolateLuma8( Short const *src , Int srcStride , __m128i *mmCoeff , const __m128i & mmOffset , Int shift ) { __m128i sumHi = _mm_setzero_si128(); __m128i sumLo = _mm_setzero_si128(); for( Int n = 0 ; n < 8 ; n++ ) { __m128i mmPix = _mm_loadu_si128( ( __m128i* )src ); __m128i hi = _mm_mulhi_epi16( mmPix , mmCoeff[n] ); __m128i lo = _mm_mullo_epi16( mmPix , mmCoeff[n] ); sumHi = _mm_add_epi32( sumHi , _mm_unpackhi_epi16( lo , hi ) ); sumLo = _mm_add_epi32( sumLo , _mm_unpacklo_epi16( lo , hi ) ); src += srcStride; } sumHi = _mm_srai_epi32( _mm_add_epi32( sumHi , mmOffset ) , shift ); sumLo = _mm_srai_epi32( _mm_add_epi32( sumLo , mmOffset ) , shift ); return( _mm_packs_epi32( sumLo , sumHi ) ); } inline __m128i simdInterpolateLuma2P8( Short const *src , Int srcStride , __m128i *mmCoeff , const __m128i & mmOffset , Int shift ) { __m128i sumHi = _mm_setzero_si128(); __m128i sumLo = _mm_setzero_si128(); for( Int n = 0 ; n < 2 ; n++ ) { __m128i mmPix = _mm_loadu_si128( ( __m128i* )src ); __m128i hi = _mm_mulhi_epi16( mmPix , mmCoeff[n] ); __m128i lo = _mm_mullo_epi16( mmPix , mmCoeff[n] ); sumHi = _mm_add_epi32( sumHi , _mm_unpackhi_epi16( lo , hi ) ); sumLo = _mm_add_epi32( sumLo , _mm_unpacklo_epi16( lo , hi ) ); src += srcStride; } sumHi = _mm_srai_epi32( _mm_add_epi32( sumHi , mmOffset ) , shift ); sumLo = _mm_srai_epi32( _mm_add_epi32( sumLo , mmOffset ) , shift ); return( _mm_packs_epi32( sumLo , sumHi ) ); } inline __m128i simdInterpolateLuma2P4( Short const *src , Int srcStride , __m128i *mmCoeff , const __m128i & mmOffset , Int shift ) { __m128i sumHi = _mm_setzero_si128(); __m128i sumLo = _mm_setzero_si128(); for( Int n = 0 ; n < 2 ; n++ ) { __m128i mmPix = _mm_loadl_epi64( ( __m128i* )src ); __m128i hi = _mm_mulhi_epi16( mmPix , mmCoeff[n] ); __m128i lo = _mm_mullo_epi16( mmPix , mmCoeff[n] ); sumHi = _mm_add_epi32( sumHi , _mm_unpackhi_epi16( lo , hi ) ); sumLo = _mm_add_epi32( sumLo , _mm_unpacklo_epi16( lo , hi ) ); src += srcStride; } sumHi = _mm_srai_epi32( _mm_add_epi32( sumHi , mmOffset ) , shift ); sumLo = _mm_srai_epi32( _mm_add_epi32( sumLo , mmOffset ) , shift ); return( _mm_packs_epi32( sumLo , sumHi ) ); } inline __m128i simdClip3( __m128i mmMin , __m128i mmMax , __m128i mmPix ) { __m128i mmMask = _mm_cmpgt_epi16( mmPix , mmMin ); mmPix = _mm_or_si128( _mm_and_si128( mmMask , mmPix ) , _mm_andnot_si128( mmMask , mmMin ) ); mmMask = _mm_cmplt_epi16( mmPix , mmMax ); mmPix = _mm_or_si128( _mm_and_si128( mmMask , mmPix ) , _mm_andnot_si128( mmMask , mmMax ) ); return( mmPix ); } #endif // ==================================================================================================================== // Private member functions // ==================================================================================================================== /** * \brief Apply unit FIR filter to a block of samples * * \param bitDepth bitDepth of samples * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param isFirst Flag indicating whether it is the first filtering operation * \param isLast Flag indicating whether it is the last filtering operation */ Void TComInterpolationFilter::filterCopy(Int bitDepth, const Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isFirst, Bool isLast) { Int row, col; if ( isFirst == isLast ) { for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { dst[col] = src[col]; } src += srcStride; dst += dstStride; } } else if ( isFirst ) { const Int shift = std::max(2, (IF_INTERNAL_PREC - bitDepth)); for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { Pel val = leftShift_round(src[col], shift); dst[col] = val - (Pel)IF_INTERNAL_OFFS; } src += srcStride; dst += dstStride; } } else { const Int shift = std::max(2, (IF_INTERNAL_PREC - bitDepth)); Pel maxVal = (1 << bitDepth) - 1; Pel minVal = 0; for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { Pel val = src[ col ]; val = rightShift_round((val + IF_INTERNAL_OFFS), shift); if (val < minVal) { val = minVal; } if (val > maxVal) { val = maxVal; } dst[col] = val; } src += srcStride; dst += dstStride; } } } /** * \brief Apply FIR filter to a block of samples * * \tparam N Number of taps * \tparam isVertical Flag indicating filtering along vertical direction * \tparam isFirst Flag indicating whether it is the first filtering operation * \tparam isLast Flag indicating whether it is the last filtering operation * \param bitDepth Bit depth of samples * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param coeff Pointer to filter taps */ template Void TComInterpolationFilter::filter(Int bitDepth, Pel const *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, TFilterCoeff const *coeff) { Int row, col; Pel c[8]; c[0] = coeff[0]; c[1] = coeff[1]; if ( N >= 4 ) { c[2] = coeff[2]; c[3] = coeff[3]; } if ( N >= 6 ) { c[4] = coeff[4]; c[5] = coeff[5]; } if ( N == 8 ) { c[6] = coeff[6]; c[7] = coeff[7]; } Int cStride = ( isVertical ) ? srcStride : 1; src -= ( N/2 - 1 ) * cStride; Int offset; Pel maxVal; Int headRoom = std::max(2, (IF_INTERNAL_PREC - bitDepth)); Int shift = IF_FILTER_PREC; // with the current settings (IF_INTERNAL_PREC = 14 and IF_FILTER_PREC = 6), though headroom can be // negative for bit depths greater than 14, shift will remain non-negative for bit depths of 8->20 assert(shift >= 0); if ( isLast ) { shift += (isFirst) ? 0 : headRoom; offset = 1 << (shift - 1); offset += (isFirst) ? 0 : IF_INTERNAL_OFFS << IF_FILTER_PREC; maxVal = (1 << bitDepth) - 1; } else { shift -= (isFirst) ? headRoom : 0; offset = (isFirst) ? -IF_INTERNAL_OFFS << shift : 0; maxVal = 0; } #if VECTOR_CODING__INTERPOLATION_FILTER && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( bitDepth <= 10 ) { if( N == 8 && !( width & 0x07 ) ) { Short minVal = 0; __m128i mmOffset = _mm_set1_epi32( offset ); __m128i mmCoeff[8]; __m128i mmMin = _mm_set1_epi16( minVal ); __m128i mmMax = _mm_set1_epi16( maxVal ); for( Int n = 0 ; n < 8 ; n++ ) mmCoeff[n] = _mm_set1_epi16( c[n] ); for( row = 0 ; row < height ; row++ ) { for( col = 0 ; col < width ; col += 8 ) { __m128i mmFiltered = simdInterpolateLuma8( src + col , cStride , mmCoeff , mmOffset , shift ); if( isLast ) { mmFiltered = simdClip3( mmMin , mmMax , mmFiltered ); } _mm_storeu_si128( ( __m128i * )( dst + col ) , mmFiltered ); } src += srcStride; dst += dstStride; } return; } else if( N == 8 && !( width & 0x03 ) ) { Short minVal = 0; __m128i mmOffset = _mm_set1_epi32( offset ); __m128i mmCoeff[8]; __m128i mmMin = _mm_set1_epi16( minVal ); __m128i mmMax = _mm_set1_epi16( maxVal ); for( Int n = 0 ; n < 8 ; n++ ) mmCoeff[n] = _mm_set1_epi16( c[n] ); for( row = 0 ; row < height ; row++ ) { for( col = 0 ; col < width ; col += 4 ) { __m128i mmFiltered = simdInterpolateLuma4( src + col , cStride , mmCoeff , mmOffset , shift ); if( isLast ) { mmFiltered = simdClip3( mmMin , mmMax , mmFiltered ); } _mm_storel_epi64( ( __m128i * )( dst + col ) , mmFiltered ); } src += srcStride; dst += dstStride; } return; } else if( N == 4 && !( width & 0x03 ) ) { Short minVal = 0; __m128i mmOffset = _mm_set1_epi32( offset ); __m128i mmCoeff[8]; __m128i mmMin = _mm_set1_epi16( minVal ); __m128i mmMax = _mm_set1_epi16( maxVal ); for( Int n = 0 ; n < 4 ; n++ ) mmCoeff[n] = _mm_set1_epi16( c[n] ); for( row = 0 ; row < height ; row++ ) { for( col = 0 ; col < width ; col += 4 ) { __m128i mmFiltered = simdInterpolateChroma4( src + col , cStride , mmCoeff , mmOffset , shift ); if( isLast ) { mmFiltered = simdClip3( mmMin , mmMax , mmFiltered ); } _mm_storel_epi64( ( __m128i * )( dst + col ) , mmFiltered ); } src += srcStride; dst += dstStride; } return; } else if( N == 2 && !( width & 0x07 ) ) { Short minVal = 0; __m128i mmOffset = _mm_set1_epi32( offset ); __m128i mmCoeff[2]; __m128i mmMin = _mm_set1_epi16( minVal ); __m128i mmMax = _mm_set1_epi16( maxVal ); for( Int n = 0 ; n < 2 ; n++ ) mmCoeff[n] = _mm_set1_epi16( c[n] ); for( row = 0 ; row < height ; row++ ) { for( col = 0 ; col < width ; col += 8 ) { __m128i mmFiltered = simdInterpolateLuma2P8( src + col , cStride , mmCoeff , mmOffset , shift ); if( isLast ) { mmFiltered = simdClip3( mmMin , mmMax , mmFiltered ); } _mm_storeu_si128( ( __m128i * )( dst + col ) , mmFiltered ); } src += srcStride; dst += dstStride; } return; } else if( N == 2 && !( width & 0x03 ) ) { Short minVal = 0; __m128i mmOffset = _mm_set1_epi32( offset ); __m128i mmCoeff[8]; __m128i mmMin = _mm_set1_epi16( minVal ); __m128i mmMax = _mm_set1_epi16( maxVal ); for( Int n = 0 ; n < 2 ; n++ ) mmCoeff[n] = _mm_set1_epi16( c[n] ); for( row = 0 ; row < height ; row++ ) { for( col = 0 ; col < width ; col += 4 ) { __m128i mmFiltered = simdInterpolateLuma2P4( src + col , cStride , mmCoeff , mmOffset , shift ); if( isLast ) { mmFiltered = simdClip3( mmMin , mmMax , mmFiltered ); } _mm_storel_epi64( ( __m128i * )( dst + col ) , mmFiltered ); } src += srcStride; dst += dstStride; } return; } } #endif for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { Int sum; sum = src[ col + 0 * cStride] * c[0]; sum += src[ col + 1 * cStride] * c[1]; if ( N >= 4 ) { sum += src[ col + 2 * cStride] * c[2]; sum += src[ col + 3 * cStride] * c[3]; } if ( N >= 6 ) { sum += src[ col + 4 * cStride] * c[4]; sum += src[ col + 5 * cStride] * c[5]; } if ( N == 8 ) { sum += src[ col + 6 * cStride] * c[6]; sum += src[ col + 7 * cStride] * c[7]; } Pel val = ( sum + offset ) >> shift; if ( isLast ) { val = ( val < 0 ) ? 0 : val; val = ( val > maxVal ) ? maxVal : val; } dst[col] = val; } src += srcStride; dst += dstStride; } } /** * \brief Filter a block of samples (horizontal) * * \tparam N Number of taps * \param bitDepth Bit depth of samples * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param isLast Flag indicating whether it is the last filtering operation * \param coeff Pointer to filter taps */ template Void TComInterpolationFilter::filterHor(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isLast, TFilterCoeff const *coeff) { if ( isLast ) { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } } /** * \brief Filter a block of samples (vertical) * * \tparam N Number of taps * \param bitDepth Bit depth * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param isFirst Flag indicating whether it is the first filtering operation * \param isLast Flag indicating whether it is the last filtering operation * \param coeff Pointer to filter taps */ template Void TComInterpolationFilter::filterVer(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isFirst, Bool isLast, TFilterCoeff const *coeff) { if ( isFirst && isLast ) { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else if ( isFirst && !isLast ) { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else if ( !isFirst && isLast ) { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else { filter(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** * \brief Filter a block of Luma/Chroma samples (horizontal) * * \param compID Chroma component ID * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param frac Fractional sample offset * \param isLast Flag indicating whether it is the last filtering operation * \param fmt Chroma format * \param bitDepth Bit depth */ Void TComInterpolationFilter::filterHor(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isLast, const ChromaFormat fmt, const Int bitDepth ) { if ( frac == 0 ) { filterCopy(bitDepth, src, srcStride, dst, dstStride, width, height, true, isLast ); } else if (isLuma(compID)) { assert(frac >= 0 && frac < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterHor(bitDepth, src, srcStride, dst, dstStride, width, height, isLast, m_lumaFilter[frac]); } else { const UInt csx = getComponentScaleX(compID, fmt); assert(frac >=0 && csx<2 && (frac<<(1-csx)) < CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterHor(bitDepth, src, srcStride, dst, dstStride, width, height, isLast, m_chromaFilter[frac<<(1-csx)]); } } /** * \brief Filter a block of Luma/Chroma samples (vertical) * * \param compID Colour component ID * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param frac Fractional sample offset * \param isFirst Flag indicating whether it is the first filtering operation * \param isLast Flag indicating whether it is the last filtering operation * \param fmt Chroma format * \param bitDepth Bit depth */ Void TComInterpolationFilter::filterVer(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isFirst, Bool isLast, const ChromaFormat fmt, const Int bitDepth ) { if ( frac == 0 ) { filterCopy(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast ); } else if (isLuma(compID)) { assert(frac >= 0 && frac < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter[frac]); } else { const UInt csy = getComponentScaleY(compID, fmt); assert(frac >=0 && csy<2 && (frac<<(1-csy)) < CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_chromaFilter[frac<<(1-csy)]); } } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComInterpolationFilter.h000066400000000000000000000075071442026013100232140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** * \file * \brief Declaration of TComInterpolationFilter class */ #ifndef __TCOMINTERPOLATIONFILTER__ #define __TCOMINTERPOLATIONFILTER__ #include "CommonDef.h" //! \ingroup TLibCommon //! \{ #define NTAPS_LUMA 8 ///< Number of taps for luma #define NTAPS_CHROMA 4 ///< Number of taps for chroma #define IF_INTERNAL_PREC 14 ///< Number of bits for internal precision #define IF_FILTER_PREC 6 ///< Log2 of sum of filter taps #define IF_INTERNAL_OFFS (1<<(IF_INTERNAL_PREC-1)) ///< Offset used internally /** * \brief Interpolation filter class */ class TComInterpolationFilter { static const TFilterCoeff m_lumaFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_LUMA]; ///< Luma filter taps static const TFilterCoeff m_chromaFilter[CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_CHROMA]; ///< Chroma filter taps static Void filterCopy(Int bitDepth, const Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isFirst, Bool isLast); template static Void filter(Int bitDepth, Pel const *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, TFilterCoeff const *coeff); template static Void filterHor(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isLast, TFilterCoeff const *coeff); template static Void filterVer(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isFirst, Bool isLast, TFilterCoeff const *coeff); public: TComInterpolationFilter() {} ~TComInterpolationFilter() {} Void filterHor(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isLast, const ChromaFormat fmt, const Int bitDepth ); Void filterVer(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isFirst, Bool isLast, const ChromaFormat fmt, const Int bitDepth ); }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComList.h000066400000000000000000000064651442026013100201340ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComList.h \brief general list class (header) */ #ifndef __TCOMLIST__ #define __TCOMLIST__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include "CommonDef.h" #include using namespace std; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// list template template< class C > class TComList : public std::list< C > // NOTE: should not inherit from STL classes { public: typedef typename std::list::iterator TComIterator; TComList& operator += ( const TComList& rcTComList) { if( ! rcTComList.empty() ) { insert( this->end(), rcTComList.begin(), rcTComList.end()); } return *this; } // leszek C popBack() { C cT = this->back(); this->pop_back(); return cT; } C popFront() { C cT = this->front(); this->pop_front(); return cT; } Void pushBack( const C& rcT ) { /*assert( sizeof(C) == 4);*/ if( rcT != NULL ) { this->push_back( rcT); } } Void pushFront( const C& rcT ) { /*assert( sizeof(C) == 4);*/ if( rcT != NULL ) { this->push_front( rcT); } } TComIterator find( const C& rcT ) // leszek { return std::list< C >::find( this->begin(), this->end(), rcT ); } }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComLoopFilter.cpp000066400000000000000000001034031442026013100216210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComLoopFilter.cpp \brief deblocking filter */ #include "TComLoopFilter.h" #include "TComSlice.h" #include "TComMv.h" #include "TComTU.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constants // ==================================================================================================================== //#define EDGE_VER 0 //#define EDGE_HOR 1 #define DEFAULT_INTRA_TC_OFFSET 2 ///< Default intra TC offset // ==================================================================================================================== // Tables // ==================================================================================================================== const UChar TComLoopFilter::sm_tcTable[MAX_QP + 1 + DEFAULT_INTRA_TC_OFFSET] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,6,6,7,8,9,10,11,13,14,16,18,20,22,24 }; const UChar TComLoopFilter::sm_betaTable[MAX_QP + 1] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64 }; // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TComLoopFilter::TComLoopFilter() : m_uiNumPartitions(0) , m_bLFCrossTileBoundary(true) { for( Int edgeDir = 0; edgeDir < NUM_EDGE_DIR; edgeDir++ ) { m_aapucBS [edgeDir] = NULL; m_aapbEdgeFilter[edgeDir] = NULL; } } TComLoopFilter::~TComLoopFilter() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TComLoopFilter::setCfg( Bool bLFCrossTileBoundary ) { m_bLFCrossTileBoundary = bLFCrossTileBoundary; } Void TComLoopFilter::create( UInt uiMaxCUDepth ) { destroy(); m_uiNumPartitions = 1 << ( uiMaxCUDepth<<1 ); for( Int edgeDir = 0; edgeDir < NUM_EDGE_DIR; edgeDir++ ) { m_aapucBS [edgeDir] = new UChar[m_uiNumPartitions]; m_aapbEdgeFilter[edgeDir] = new Bool [m_uiNumPartitions]; } } Void TComLoopFilter::destroy() { for( Int edgeDir = 0; edgeDir < NUM_EDGE_DIR; edgeDir++ ) { if (m_aapucBS[edgeDir] != NULL) { delete [] m_aapucBS[edgeDir]; m_aapucBS[edgeDir] = NULL; } if (m_aapbEdgeFilter[edgeDir]) { delete [] m_aapbEdgeFilter[edgeDir]; m_aapbEdgeFilter[edgeDir] = NULL; } } } /** - call deblocking function for every CU . \param pcPic picture class (TComPic) pointer */ Void TComLoopFilter::loopFilterPic( TComPic* pcPic ) { // Horizontal filtering for ( UInt ctuRsAddr = 0; ctuRsAddr < pcPic->getNumberOfCtusInFrame(); ctuRsAddr++ ) { TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); ::memset( m_aapucBS [EDGE_VER], 0, sizeof( UChar ) * m_uiNumPartitions ); ::memset( m_aapbEdgeFilter[EDGE_VER], 0, sizeof( Bool ) * m_uiNumPartitions ); // CU-based deblocking xDeblockCU( pCtu, 0, 0, EDGE_VER ); } // Vertical filtering for ( UInt ctuRsAddr = 0; ctuRsAddr < pcPic->getNumberOfCtusInFrame(); ctuRsAddr++ ) { TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); ::memset( m_aapucBS [EDGE_HOR], 0, sizeof( UChar ) * m_uiNumPartitions ); ::memset( m_aapbEdgeFilter[EDGE_HOR], 0, sizeof( Bool ) * m_uiNumPartitions ); // CU-based deblocking xDeblockCU( pCtu, 0, 0, EDGE_HOR ); } } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== /** Deblocking filter process in CU-based (the same function as conventional's) \param pcCU Pointer to CTU/CU structure \param uiAbsZorderIdx Position in CU \param uiDepth Depth in CU \param edgeDir the direction of the edge in block boundary (horizontal/vertical), which is added newly */ Void TComLoopFilter::xDeblockCU( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, DeblockEdgeDir edgeDir ) { if(pcCU->getPic()==0||pcCU->getPartitionSize(uiAbsZorderIdx)==NUMBER_OF_PART_SIZES) { return; } TComPic* pcPic = pcCU->getPic(); UInt uiCurNumParts = pcPic->getNumPartitionsInCtu() >> (uiDepth<<1); UInt uiQNumParts = uiCurNumParts>>2; const TComSPS &sps = *(pcCU->getSlice()->getSPS()); if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth ) { for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts ) { UInt uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ]; UInt uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ]; if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ) { xDeblockCU( pcCU, uiAbsZorderIdx, uiDepth+1, edgeDir ); } } return; } xSetLoopfilterParam( pcCU, uiAbsZorderIdx ); TComTURecurse tuRecurse(pcCU, uiAbsZorderIdx); xSetEdgefilterTU ( tuRecurse ); xSetEdgefilterPU ( pcCU, uiAbsZorderIdx ); const UInt uiPelsInPart = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); for( UInt uiPartIdx = uiAbsZorderIdx; uiPartIdx < uiAbsZorderIdx + uiCurNumParts; uiPartIdx++ ) { UInt uiBSCheck; if( uiPelsInPart == 4 ) { uiBSCheck = (edgeDir == EDGE_VER && uiPartIdx%2 == 0) || (edgeDir == EDGE_HOR && (uiPartIdx-((uiPartIdx>>2)<<2))/2 == 0); } else { uiBSCheck = 1; } if ( m_aapbEdgeFilter[edgeDir][uiPartIdx] && uiBSCheck ) { xGetBoundaryStrengthSingle ( pcCU, edgeDir, uiPartIdx ); } } UInt PartIdxIncr = DEBLOCK_SMALLEST_BLOCK / uiPelsInPart ? DEBLOCK_SMALLEST_BLOCK / uiPelsInPart : 1 ; UInt uiSizeInPU = pcPic->getNumPartInCtuWidth()>>(uiDepth); const ChromaFormat chFmt=pcPic->getChromaFormat(); const UInt shiftFactor = edgeDir == EDGE_VER ? pcPic->getComponentScaleX(COMPONENT_Cb) : pcPic->getComponentScaleY(COMPONENT_Cb); const Bool bAlwaysDoChroma=chFmt==CHROMA_444; for ( Int iEdge = 0; iEdge < uiSizeInPU ; iEdge+=PartIdxIncr) { xEdgeFilterLuma ( pcCU, uiAbsZorderIdx, uiDepth, edgeDir, iEdge ); if ( chFmt!=CHROMA_400 && (bAlwaysDoChroma || (uiPelsInPart>DEBLOCK_SMALLEST_BLOCK) || (iEdge % ( (DEBLOCK_SMALLEST_BLOCK<getPic()->getNumPartInCtuWidth () >> uiDepth; } if ( uiHeightInBaseUnits == 0 ) { uiHeightInBaseUnits = pcCU->getPic()->getNumPartInCtuHeight() >> uiDepth; } const UInt uiNumElem = edgeDir == EDGE_VER ? uiHeightInBaseUnits : uiWidthInBaseUnits; assert( uiNumElem > 0 ); assert( uiWidthInBaseUnits > 0 ); assert( uiHeightInBaseUnits > 0 ); for( UInt ui = 0; ui < uiNumElem; ui++ ) { const UInt uiBsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, edgeDir, iEdgeIdx, ui, rect ); m_aapbEdgeFilter[edgeDir][uiBsIdx] = bValue; if (iEdgeIdx == 0) { m_aapucBS[edgeDir][uiBsIdx] = bValue; } } } Void TComLoopFilter::xSetEdgefilterTU( TComTU &rTu ) { TComDataCU* pcCU = rTu.getCU(); UInt uiTransDepthTotal = rTu.GetTransformDepthTotal(); if( pcCU->getTransformIdx( rTu.GetAbsPartIdxTU() ) + pcCU->getDepth( rTu.GetAbsPartIdxTU()) > uiTransDepthTotal ) { TComTURecurse tuChild(rTu, false); do { xSetEdgefilterTU( tuChild ); } while (tuChild.nextSection(rTu)); return; } const TComRectangle &rect = rTu.getRect(COMPONENT_Y); const TComSPS &sps=*(pcCU->getSlice()->getSPS()); const UInt uiWidthInBaseUnits = rect.width / (sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth()); const UInt uiHeightInBaseUnits = rect.height / (sps.getMaxCUHeight() >> sps.getMaxTotalCUDepth()); xSetEdgefilterMultiple( pcCU, rTu.GetAbsPartIdxCU(), uiTransDepthTotal, EDGE_VER, 0, m_stLFCUParam.bInternalEdge, uiWidthInBaseUnits, uiHeightInBaseUnits, &rect ); xSetEdgefilterMultiple( pcCU, rTu.GetAbsPartIdxCU(), uiTransDepthTotal, EDGE_HOR, 0, m_stLFCUParam.bInternalEdge, uiWidthInBaseUnits, uiHeightInBaseUnits, &rect ); } Void TComLoopFilter::xSetEdgefilterPU( TComDataCU* pcCU, UInt uiAbsZorderIdx ) { const UInt uiDepth = pcCU->getDepth( uiAbsZorderIdx ); const UInt uiWidthInBaseUnits = pcCU->getPic()->getNumPartInCtuWidth () >> uiDepth; const UInt uiHeightInBaseUnits = pcCU->getPic()->getNumPartInCtuHeight() >> uiDepth; const UInt uiHWidthInBaseUnits = uiWidthInBaseUnits >> 1; const UInt uiHHeightInBaseUnits = uiHeightInBaseUnits >> 1; const UInt uiQWidthInBaseUnits = uiWidthInBaseUnits >> 2; const UInt uiQHeightInBaseUnits = uiHeightInBaseUnits >> 2; xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, 0, m_stLFCUParam.bLeftEdge ); xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, 0, m_stLFCUParam.bTopEdge ); switch ( pcCU->getPartitionSize( uiAbsZorderIdx ) ) { case SIZE_2Nx2N: { break; } case SIZE_2NxN: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHHeightInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_Nx2N: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiHWidthInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_NxN: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiHWidthInBaseUnits, m_stLFCUParam.bInternalEdge ); xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHHeightInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_2NxnU: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiQHeightInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_2NxnD: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_HOR, uiHeightInBaseUnits - uiQHeightInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_nLx2N: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiQWidthInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } case SIZE_nRx2N: { xSetEdgefilterMultiple( pcCU, uiAbsZorderIdx, uiDepth, EDGE_VER, uiWidthInBaseUnits - uiQWidthInBaseUnits, m_stLFCUParam.bInternalEdge ); break; } default: { break; } } } Void TComLoopFilter::xSetLoopfilterParam( TComDataCU* pcCU, UInt uiAbsZorderIdx ) { UInt uiX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[ uiAbsZorderIdx ] ]; UInt uiY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[ uiAbsZorderIdx ] ]; UInt uiTempPartIdx; m_stLFCUParam.bInternalEdge = ! pcCU->getSlice()->getDeblockingFilterDisable(); if ( (uiX == 0) || pcCU->getSlice()->getDeblockingFilterDisable() ) { m_stLFCUParam.bLeftEdge = false; } else { m_stLFCUParam.bLeftEdge = true; } if ( m_stLFCUParam.bLeftEdge ) { const TComDataCU* pcTempCU = pcCU->getPULeft( uiTempPartIdx, uiAbsZorderIdx, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), !m_bLFCrossTileBoundary); if ( pcTempCU != NULL ) { m_stLFCUParam.bLeftEdge = true; } else { m_stLFCUParam.bLeftEdge = false; } } if ( (uiY == 0 ) || pcCU->getSlice()->getDeblockingFilterDisable() ) { m_stLFCUParam.bTopEdge = false; } else { m_stLFCUParam.bTopEdge = true; } if ( m_stLFCUParam.bTopEdge ) { const TComDataCU* pcTempCU = pcCU->getPUAbove( uiTempPartIdx, uiAbsZorderIdx, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary); if ( pcTempCU != NULL ) { m_stLFCUParam.bTopEdge = true; } else { m_stLFCUParam.bTopEdge = false; } } } Void TComLoopFilter::xGetBoundaryStrengthSingle ( TComDataCU* pCtu, DeblockEdgeDir edgeDir, UInt uiAbsPartIdx4x4BlockWithinCtu ) { TComSlice * const pcSlice = pCtu->getSlice(); const Bool lfCrossSliceBoundaryFlag=pCtu->getSlice()->getLFCrossSliceBoundaryFlag(); const UInt uiPartQ = uiAbsPartIdx4x4BlockWithinCtu; TComDataCU* const pcCUQ = pCtu; UInt uiPartP; const TComDataCU* pcCUP; UInt uiBs = 0; //-- Calculate Block Index if (edgeDir == EDGE_VER) { pcCUP = pcCUQ->getPULeft(uiPartP, uiPartQ, !lfCrossSliceBoundaryFlag, !m_bLFCrossTileBoundary); } else // (edgeDir == EDGE_HOR) { pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pCtu->getSlice()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary); } //-- Set BS for Intra MB : BS = 4 or 3 if ( pcCUP->isIntra(uiPartP) || pcCUQ->isIntra(uiPartQ) ) { uiBs = 2; } //-- Set BS for not Intra MB : BS = 2 or 1 or 0 if ( !pcCUP->isIntra(uiPartP) && !pcCUQ->isIntra(uiPartQ) ) { UInt nsPartQ = uiPartQ; UInt nsPartP = uiPartP; if ( m_aapucBS[edgeDir][uiAbsPartIdx4x4BlockWithinCtu] && (pcCUQ->getCbf( nsPartQ, COMPONENT_Y, pcCUQ->getTransformIdx(nsPartQ)) != 0 || pcCUP->getCbf( nsPartP, COMPONENT_Y, pcCUP->getTransformIdx(nsPartP) ) != 0) ) { uiBs = 1; } else { if (pcSlice->isInterB() || pcCUP->getSlice()->isInterB()) { Int iRefIdx; iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP); const TComPic *piRefP0 = (iRefIdx < 0) ? NULL : pcCUP->getSlice()->getRefPic(REF_PIC_LIST_0, iRefIdx); iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartP); const TComPic *piRefP1 = (iRefIdx < 0) ? NULL : pcCUP->getSlice()->getRefPic(REF_PIC_LIST_1, iRefIdx); iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ); const TComPic *piRefQ0 = (iRefIdx < 0) ? NULL : pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx); iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartQ); const TComPic *piRefQ1 = (iRefIdx < 0) ? NULL : pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx); TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP); TComMv pcMvP1 = pcCUP->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartP); TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ); TComMv pcMvQ1 = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartQ); if (piRefP0 == NULL) { pcMvP0.setZero(); } if (piRefP1 == NULL) { pcMvP1.setZero(); } if (piRefQ0 == NULL) { pcMvQ0.setZero(); } if (piRefQ1 == NULL) { pcMvQ1.setZero(); } if ( ((piRefP0==piRefQ0)&&(piRefP1==piRefQ1)) || ((piRefP0==piRefQ1)&&(piRefP1==piRefQ0)) ) { if ( piRefP0 != piRefP1 ) // Different L0 & L1 { if ( piRefP0 == piRefQ0 ) { uiBs = ((abs(pcMvQ0.getHor() - pcMvP0.getHor()) >= 4) || (abs(pcMvQ0.getVer() - pcMvP0.getVer()) >= 4) || (abs(pcMvQ1.getHor() - pcMvP1.getHor()) >= 4) || (abs(pcMvQ1.getVer() - pcMvP1.getVer()) >= 4)) ? 1 : 0; } else { uiBs = ((abs(pcMvQ1.getHor() - pcMvP0.getHor()) >= 4) || (abs(pcMvQ1.getVer() - pcMvP0.getVer()) >= 4) || (abs(pcMvQ0.getHor() - pcMvP1.getHor()) >= 4) || (abs(pcMvQ0.getVer() - pcMvP1.getVer()) >= 4)) ? 1 : 0; } } else // Same L0 & L1 { uiBs = ((abs(pcMvQ0.getHor() - pcMvP0.getHor()) >= 4) || (abs(pcMvQ0.getVer() - pcMvP0.getVer()) >= 4) || (abs(pcMvQ1.getHor() - pcMvP1.getHor()) >= 4) || (abs(pcMvQ1.getVer() - pcMvP1.getVer()) >= 4)) && ((abs(pcMvQ1.getHor() - pcMvP0.getHor()) >= 4) || (abs(pcMvQ1.getVer() - pcMvP0.getVer()) >= 4) || (abs(pcMvQ0.getHor() - pcMvP1.getHor()) >= 4) || (abs(pcMvQ0.getVer() - pcMvP1.getVer()) >= 4)) ? 1 : 0; } } else // for all different Ref_Idx { uiBs = 1; } } else // pcSlice->isInterP() { Int iRefIdx; iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP); const TComPic *piRefP0 = (iRefIdx < 0) ? NULL : pcCUP->getSlice()->getRefPic(REF_PIC_LIST_0, iRefIdx); iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ); const TComPic *piRefQ0 = (iRefIdx < 0) ? NULL : pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx); TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP); TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ); if (piRefP0 == NULL) { pcMvP0.setZero(); } if (piRefQ0 == NULL) { pcMvQ0.setZero(); } uiBs = ((piRefP0 != piRefQ0) || (abs(pcMvQ0.getHor() - pcMvP0.getHor()) >= 4) || (abs(pcMvQ0.getVer() - pcMvP0.getVer()) >= 4)) ? 1 : 0; } } // enf of "if( one of BCBP == 0 )" } // enf of "if( not Intra )" m_aapucBS[edgeDir][uiAbsPartIdx4x4BlockWithinCtu] = uiBs; } Void TComLoopFilter::xEdgeFilterLuma( TComDataCU* const pcCU, const UInt uiAbsZorderIdx, const UInt uiDepth, const DeblockEdgeDir edgeDir, const Int iEdge ) { TComPicYuv *pcPicYuvRec = pcCU->getPic()->getPicYuvRec(); Pel *piSrc = pcPicYuvRec->getAddr(COMPONENT_Y, pcCU->getCtuRsAddr(), uiAbsZorderIdx ); Pel *piTmpSrc = piSrc; const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const Bool ppsTransquantBypassEnabledFlag = pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag(); const Int bitDepthLuma = sps.getBitDepth(CHANNEL_TYPE_LUMA); const Bool lfCrossSliceBoundaryFlag = pcCU->getSlice()->getLFCrossSliceBoundaryFlag(); Int iStride = pcPicYuvRec->getStride(COMPONENT_Y); Int iQP = 0; Int iQP_P = 0; Int iQP_Q = 0; UInt uiNumParts = pcCU->getPic()->getNumPartInCtuWidth()>>uiDepth; UInt uiPelsInPart = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); UInt uiBsAbsIdx = 0, uiBs = 0; Int iOffset, iSrcStep; Bool bPCMFilter = (sps.getUsePCM() && sps.getPCMFilterDisableFlag())? true : false; Bool bPartPNoFilter = false; Bool bPartQNoFilter = false; UInt uiPartPIdx = 0; UInt uiPartQIdx = 0; const TComDataCU* pcCUP = pcCU; TComDataCU* pcCUQ = pcCU; Int betaOffsetDiv2 = pcCUQ->getSlice()->getDeblockingFilterBetaOffsetDiv2(); Int tcOffsetDiv2 = pcCUQ->getSlice()->getDeblockingFilterTcOffsetDiv2(); if (edgeDir == EDGE_VER) { iOffset = 1; iSrcStep = iStride; piTmpSrc += iEdge*uiPelsInPart; } else // (edgeDir == EDGE_HOR) { iOffset = iStride; iSrcStep = 1; piTmpSrc += iEdge*uiPelsInPart*iStride; } const Int iBitdepthScale = 1 << (bitDepthLuma-8); for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx++ ) { uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, edgeDir, iEdge, iIdx); uiBs = m_aapucBS[edgeDir][uiBsAbsIdx]; if ( uiBs ) { iQP_Q = pcCU->getQP( uiBsAbsIdx ); uiPartQIdx = uiBsAbsIdx; // Derive neighboring PU index if (edgeDir == EDGE_VER) { pcCUP = pcCUQ->getPULeft (uiPartPIdx, uiPartQIdx,!lfCrossSliceBoundaryFlag, !m_bLFCrossTileBoundary); } else // (iDir == EDGE_HOR) { pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!lfCrossSliceBoundaryFlag, false, !m_bLFCrossTileBoundary); } iQP_P = pcCUP->getQP(uiPartPIdx); iQP = (iQP_P + iQP_Q + 1) >> 1; Int iIndexTC = Clip3(0, MAX_QP+DEFAULT_INTRA_TC_OFFSET, Int(iQP + DEFAULT_INTRA_TC_OFFSET*(uiBs-1) + (tcOffsetDiv2 << 1))); Int iIndexB = Clip3(0, MAX_QP, iQP + (betaOffsetDiv2 << 1)); Int iTc = sm_tcTable[iIndexTC]*iBitdepthScale; Int iBeta = sm_betaTable[iIndexB]*iBitdepthScale; Int iSideThreshold = (iBeta+(iBeta>>1))>>3; Int iThrCut = iTc*10; UInt uiBlocksInPart = uiPelsInPart / 4 ? uiPelsInPart / 4 : 1; for (UInt iBlkIdx = 0; iBlkIdxgetIPCMFlag(uiPartPIdx)); bPartQNoFilter = (bPCMFilter && pcCUQ->getIPCMFlag(uiPartQIdx)); // check if each of PUs is lossless coded bPartPNoFilter = bPartPNoFilter || (pcCUP->isLosslessCoded(uiPartPIdx) ); bPartQNoFilter = bPartQNoFilter || (pcCUQ->isLosslessCoded(uiPartQIdx) ); } if (d < iBeta) { Bool bFilterP = (dp < iSideThreshold); Bool bFilterQ = (dq < iSideThreshold); Bool sw = xUseStrongFiltering( iOffset, 2*d0, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+0)) && xUseStrongFiltering( iOffset, 2*d3, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+3)); for ( Int i = 0; i < DEBLOCK_SMALLEST_BLOCK/2; i++) { xPelFilterLuma( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+i), iOffset, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ, bitDepthLuma); } } } } } } Void TComLoopFilter::xEdgeFilterChroma( TComDataCU* const pcCU, const UInt uiAbsZorderIdx, const UInt uiDepth, const DeblockEdgeDir edgeDir, const Int iEdge ) { TComPicYuv *pcPicYuvRec = pcCU->getPic()->getPicYuvRec(); Int iStride = pcPicYuvRec->getStride(COMPONENT_Cb); Pel *piSrcCb = pcPicYuvRec->getAddr( COMPONENT_Cb, pcCU->getCtuRsAddr(), uiAbsZorderIdx ); Pel *piSrcCr = pcPicYuvRec->getAddr( COMPONENT_Cr, pcCU->getCtuRsAddr(), uiAbsZorderIdx ); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const Int bitDepthChroma = sps.getBitDepth(CHANNEL_TYPE_CHROMA); const UInt uiPelsInPartChromaH = sps.getMaxCUWidth() >> (sps.getMaxTotalCUDepth()+pcPicYuvRec->getComponentScaleX(COMPONENT_Cb)); const UInt uiPelsInPartChromaV = sps.getMaxCUHeight() >> (sps.getMaxTotalCUDepth()+pcPicYuvRec->getComponentScaleY(COMPONENT_Cb)); Int iQP = 0; Int iQP_P = 0; Int iQP_Q = 0; Int iOffset, iSrcStep; UInt uiLoopLength; const UInt uiCtuWidthInBaseUnits = pcCU->getPic()->getNumPartInCtuWidth(); Bool bPCMFilter = (pcCU->getSlice()->getSPS()->getUsePCM() && pcCU->getSlice()->getSPS()->getPCMFilterDisableFlag())? true : false; Bool bPartPNoFilter = false; Bool bPartQNoFilter = false; TComDataCU* pcCUQ = pcCU; Int tcOffsetDiv2 = pcCU->getSlice()->getDeblockingFilterTcOffsetDiv2(); // Vertical Position UInt uiEdgeNumInCtuVert = g_auiZscanToRaster[uiAbsZorderIdx]%uiCtuWidthInBaseUnits + iEdge; UInt uiEdgeNumInCtuHor = g_auiZscanToRaster[uiAbsZorderIdx]/uiCtuWidthInBaseUnits + iEdge; if ( (uiPelsInPartChromaH < DEBLOCK_SMALLEST_BLOCK) && (uiPelsInPartChromaV < DEBLOCK_SMALLEST_BLOCK) && ( ( (uiEdgeNumInCtuVert%(DEBLOCK_SMALLEST_BLOCK/uiPelsInPartChromaH)) && (edgeDir==EDGE_VER) ) || ( (uiEdgeNumInCtuHor %(DEBLOCK_SMALLEST_BLOCK/uiPelsInPartChromaV)) && (edgeDir==EDGE_HOR) ) ) ) { return; } const Bool lfCrossSliceBoundaryFlag=pcCU->getSlice()->getLFCrossSliceBoundaryFlag(); UInt uiNumParts = pcCU->getPic()->getNumPartInCtuWidth()>>uiDepth; UInt uiBsAbsIdx; UChar ucBs; Pel* piTmpSrcCb = piSrcCb; Pel* piTmpSrcCr = piSrcCr; if (edgeDir == EDGE_VER) { iOffset = 1; iSrcStep = iStride; piTmpSrcCb += iEdge*uiPelsInPartChromaH; piTmpSrcCr += iEdge*uiPelsInPartChromaH; uiLoopLength=uiPelsInPartChromaV; } else // (edgeDir == EDGE_HOR) { iOffset = iStride; iSrcStep = 1; piTmpSrcCb += iEdge*iStride*uiPelsInPartChromaV; piTmpSrcCr += iEdge*iStride*uiPelsInPartChromaV; uiLoopLength=uiPelsInPartChromaH; } const Int iBitdepthScale = 1 << (pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA)-8); for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx++ ) { uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, edgeDir, iEdge, iIdx); ucBs = m_aapucBS[edgeDir][uiBsAbsIdx]; if ( ucBs > 1) { iQP_Q = pcCU->getQP( uiBsAbsIdx ); UInt uiPartQIdx = uiBsAbsIdx; // Derive neighboring PU index const TComDataCU* pcCUP; UInt uiPartPIdx; if (edgeDir == EDGE_VER) { pcCUP = pcCUQ->getPULeft (uiPartPIdx, uiPartQIdx,!lfCrossSliceBoundaryFlag, !m_bLFCrossTileBoundary); } else // (edgeDir == EDGE_HOR) { pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!lfCrossSliceBoundaryFlag, false, !m_bLFCrossTileBoundary); } iQP_P = pcCUP->getQP(uiPartPIdx); if (bPCMFilter || pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { // Check if each of PUs is I_PCM with LF disabling bPartPNoFilter = (bPCMFilter && pcCUP->getIPCMFlag(uiPartPIdx)); bPartQNoFilter = (bPCMFilter && pcCUQ->getIPCMFlag(uiPartQIdx)); // check if each of PUs is lossless coded bPartPNoFilter = bPartPNoFilter || (pcCUP->isLosslessCoded(uiPartPIdx)); bPartQNoFilter = bPartQNoFilter || (pcCUQ->isLosslessCoded(uiPartQIdx)); } for ( UInt chromaIdx = 0; chromaIdx < 2; chromaIdx++ ) { Int chromaQPOffset = pcCU->getSlice()->getPPS()->getQpOffset(ComponentID(chromaIdx + 1)); Pel* piTmpSrcChroma = (chromaIdx == 0) ? piTmpSrcCb : piTmpSrcCr; iQP = ((iQP_P + iQP_Q + 1) >> 1) + chromaQPOffset; if (iQP >= chromaQPMappingTableSize) { if (pcPicYuvRec->getChromaFormat()==CHROMA_420) { iQP -=6; } else if (iQP>51) { iQP=51; } } else if (iQP >= 0 ) { iQP = getScaledChromaQP(iQP, pcPicYuvRec->getChromaFormat()); } Int iIndexTC = Clip3(0, MAX_QP+DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET*(ucBs - 1) + (tcOffsetDiv2 << 1)); Int iTc = sm_tcTable[iIndexTC]*iBitdepthScale; for ( UInt uiStep = 0; uiStep < uiLoopLength; uiStep++ ) { xPelFilterChroma( piTmpSrcChroma + iSrcStep*(uiStep+iIdx*uiLoopLength), iOffset, iTc , bPartPNoFilter, bPartQNoFilter, bitDepthChroma); } } } } } /** - Deblocking for the luminance component with strong or weak filter . \param piSrc pointer to picture data \param iOffset offset value for picture data \param tc tc value \param sw decision strong/weak filter \param bPartPNoFilter indicator to disable filtering on partP \param bPartQNoFilter indicator to disable filtering on partQ \param iThrCut threshold value for weak filter decision \param bFilterSecondP decision weak filter/no filter for partP \param bFilterSecondQ decision weak filter/no filter for partQ \param bitDepthLuma luma bit depth */ __inline Void TComLoopFilter::xPelFilterLuma( Pel* piSrc, Int iOffset, Int tc, Bool sw, Bool bPartPNoFilter, Bool bPartQNoFilter, Int iThrCut, Bool bFilterSecondP, Bool bFilterSecondQ, const Int bitDepthLuma) { Int delta; Pel m4 = piSrc[0]; Pel m3 = piSrc[-iOffset]; Pel m5 = piSrc[ iOffset]; Pel m2 = piSrc[-iOffset*2]; Pel m6 = piSrc[ iOffset*2]; Pel m1 = piSrc[-iOffset*3]; Pel m7 = piSrc[ iOffset*3]; Pel m0 = piSrc[-iOffset*4]; if (sw) { piSrc[-iOffset] = Clip3(m3-2*tc, m3+2*tc, ((m1 + 2*m2 + 2*m3 + 2*m4 + m5 + 4) >> 3)); piSrc[0] = Clip3(m4-2*tc, m4+2*tc, ((m2 + 2*m3 + 2*m4 + 2*m5 + m6 + 4) >> 3)); piSrc[-iOffset*2] = Clip3(m2-2*tc, m2+2*tc, ((m1 + m2 + m3 + m4 + 2)>>2)); piSrc[ iOffset] = Clip3(m5-2*tc, m5+2*tc, ((m3 + m4 + m5 + m6 + 2)>>2)); piSrc[-iOffset*3] = Clip3(m1-2*tc, m1+2*tc, ((2*m0 + 3*m1 + m2 + m3 + m4 + 4 )>>3)); piSrc[ iOffset*2] = Clip3(m6-2*tc, m6+2*tc, ((m3 + m4 + m5 + 3*m6 + 2*m7 +4 )>>3)); } else { /* Weak filter */ delta = (9*(m4-m3) -3*(m5-m2) + 8)>>4 ; if ( abs(delta) < iThrCut ) { delta = Clip3(-tc, tc, delta); piSrc[-iOffset] = ClipBD((m3+delta), bitDepthLuma); piSrc[0] = ClipBD((m4-delta), bitDepthLuma); Int tc2 = tc>>1; if(bFilterSecondP) { Int delta1 = Clip3(-tc2, tc2, (( ((m1+m3+1)>>1)- m2+delta)>>1)); piSrc[-iOffset*2] = ClipBD((m2+delta1), bitDepthLuma); } if(bFilterSecondQ) { Int delta2 = Clip3(-tc2, tc2, (( ((m6+m4+1)>>1)- m5-delta)>>1)); piSrc[ iOffset] = ClipBD((m5+delta2), bitDepthLuma); } } } if(bPartPNoFilter) { piSrc[-iOffset] = m3; piSrc[-iOffset*2] = m2; piSrc[-iOffset*3] = m1; } if(bPartQNoFilter) { piSrc[0] = m4; piSrc[ iOffset] = m5; piSrc[ iOffset*2] = m6; } } /** - Deblocking of one line/column for the chrominance component . \param piSrc pointer to picture data \param iOffset offset value for picture data \param tc tc value \param bPartPNoFilter indicator to disable filtering on partP \param bPartQNoFilter indicator to disable filtering on partQ \param bitDepthChroma chroma bit depth */ __inline Void TComLoopFilter::xPelFilterChroma( Pel* piSrc, Int iOffset, Int tc, Bool bPartPNoFilter, Bool bPartQNoFilter, const Int bitDepthChroma) { Int delta; Pel m4 = piSrc[0]; Pel m3 = piSrc[-iOffset]; Pel m5 = piSrc[ iOffset]; Pel m2 = piSrc[-iOffset*2]; delta = Clip3(-tc,tc, (((( m4 - m3 ) << 2 ) + m2 - m5 + 4 ) >> 3) ); piSrc[-iOffset] = ClipBD((m3+delta), bitDepthChroma); piSrc[0] = ClipBD((m4-delta), bitDepthChroma); if(bPartPNoFilter) { piSrc[-iOffset] = m3; } if(bPartQNoFilter) { piSrc[0] = m4; } } /** - Decision between strong and weak filter . \param offset offset value for picture data \param d d value \param beta beta value \param tc tc value \param piSrc pointer to picture data */ __inline Bool TComLoopFilter::xUseStrongFiltering( Int offset, Int d, Int beta, Int tc, Pel* piSrc) { Pel m4 = piSrc[0]; Pel m3 = piSrc[-offset]; Pel m7 = piSrc[ offset*3]; Pel m0 = piSrc[-offset*4]; Int d_strong = abs(m0-m3) + abs(m7-m4); return ( (d_strong < (beta>>3)) && (d<(beta>>2)) && ( abs(m3-m4) < ((tc*5+1)>>1)) ); } __inline Int TComLoopFilter::xCalcDP( Pel* piSrc, Int iOffset) { return abs( piSrc[-iOffset*3] - 2*piSrc[-iOffset*2] + piSrc[-iOffset] ) ; } __inline Int TComLoopFilter::xCalcDQ( Pel* piSrc, Int iOffset) { return abs( piSrc[0] - 2*piSrc[iOffset] + piSrc[iOffset*2] ); } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComLoopFilter.h000066400000000000000000000134201442026013100212650ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComLoopFilter.h \brief deblocking filter (header) */ #ifndef __TCOMLOOPFILTER__ #define __TCOMLOOPFILTER__ #include "CommonDef.h" #include "TComPic.h" //! \ingroup TLibCommon //! \{ #define DEBLOCK_SMALLEST_BLOCK 8 // ==================================================================================================================== // Class definition // ==================================================================================================================== /// deblocking filter class class TComLoopFilter { private: UInt m_uiNumPartitions; UChar* m_aapucBS[NUM_EDGE_DIR]; ///< Bs for [Ver/Hor][Y/U/V][Blk_Idx] Bool* m_aapbEdgeFilter[NUM_EDGE_DIR]; LFCUParam m_stLFCUParam; ///< status structure Bool m_bLFCrossTileBoundary; protected: /// CU-level deblocking function Void xDeblockCU ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, DeblockEdgeDir edgeDir ); // set / get functions Void xSetLoopfilterParam ( TComDataCU* pcCU, UInt uiAbsZorderIdx ); // filtering functions Void xSetEdgefilterTU ( TComTU &rTu ); Void xSetEdgefilterPU ( TComDataCU* pcCU, UInt uiAbsZorderIdx ); Void xGetBoundaryStrengthSingle ( TComDataCU* pCtu, DeblockEdgeDir edgeDir, UInt uiPartIdx ); UInt xCalcBsIdx ( TComDataCU* pcCU, UInt absZIdxInCtu, DeblockEdgeDir edgeDir, Int iEdgeIdx, Int iBaseUnitIdx, const struct TComRectangle *rect=NULL ) { TComPic* const pcPic = pcCU->getPic(); const UInt ctuWidthInBaseUnits = pcPic->getNumPartInCtuWidth(); Int rasterOffsetTU=0; if (rect != NULL) { const UInt minCuWidth =pcPic->getMinCUWidth(); const UInt minCuHeight=pcPic->getMinCUHeight(); rasterOffsetTU = rect->x0/minCuWidth + (rect->y0/minCuHeight)*ctuWidthInBaseUnits; } if( edgeDir == EDGE_VER ) { return g_auiRasterToZscan[g_auiZscanToRaster[absZIdxInCtu] + iBaseUnitIdx * ctuWidthInBaseUnits + iEdgeIdx + rasterOffsetTU ]; } else { return g_auiRasterToZscan[g_auiZscanToRaster[absZIdxInCtu] + iEdgeIdx * ctuWidthInBaseUnits + iBaseUnitIdx + rasterOffsetTU ]; } } Void xSetEdgefilterMultiple( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, DeblockEdgeDir edgeDir, Int iEdgeIdx, Bool bValue, UInt uiWidthInBaseUnits = 0, UInt uiHeightInBaseUnits = 0, const TComRectangle *rect = 0 ); Void xEdgeFilterLuma ( TComDataCU* const pcCU, const UInt uiAbsZorderIdx, const UInt uiDepth, const DeblockEdgeDir edgeDir, const Int iEdge ); Void xEdgeFilterChroma ( TComDataCU* const pcCU, const UInt uiAbsZorderIdx, const UInt uiDepth, const DeblockEdgeDir edgeDir, const Int iEdge ); __inline Void xPelFilterLuma( Pel* piSrc, Int iOffset, Int tc, Bool sw, Bool bPartPNoFilter, Bool bPartQNoFilter, Int iThrCut, Bool bFilterSecondP, Bool bFilterSecondQ, const Int bitDepthLuma); __inline Void xPelFilterChroma( Pel* piSrc, Int iOffset, Int tc, Bool bPartPNoFilter, Bool bPartQNoFilter, const Int bitDepthChroma); __inline Bool xUseStrongFiltering( Int offset, Int d, Int beta, Int tc, Pel* piSrc); __inline Int xCalcDP( Pel* piSrc, Int iOffset); __inline Int xCalcDQ( Pel* piSrc, Int iOffset); static const UChar sm_tcTable[54]; static const UChar sm_betaTable[52]; public: TComLoopFilter(); virtual ~TComLoopFilter(); Void create ( UInt uiMaxCUDepth ); Void destroy (); /// set configuration Void setCfg( Bool bLFCrossTileBoundary ); /// picture-level deblocking filter Void loopFilterPic( TComPic* pcPic ); static Int getBeta( Int qp ) { Int indexB = Clip3( 0, MAX_QP, qp ); return sm_betaTable[ indexB ]; } }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComMotionInfo.cpp000066400000000000000000000262661442026013100216360ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComMotionInfo.cpp \brief motion information handling classes */ #include #include "TComMotionInfo.h" #include "assert.h" #include //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Public member functions // ==================================================================================================================== // -------------------------------------------------------------------------------------------------------------------- // Create / destroy // -------------------------------------------------------------------------------------------------------------------- Void TComCUMvField::create( UInt uiNumPartition ) { assert(m_pcMv == NULL); assert(m_pcMvd == NULL); assert(m_piRefIdx == NULL); m_pcMv = new TComMv[ uiNumPartition ]; m_pcMvd = new TComMv[ uiNumPartition ]; m_piRefIdx = new SChar [ uiNumPartition ]; m_uiNumPartition = uiNumPartition; } Void TComCUMvField::destroy() { assert(m_pcMv != NULL); assert(m_pcMvd != NULL); assert(m_piRefIdx != NULL); delete[] m_pcMv; delete[] m_pcMvd; delete[] m_piRefIdx; m_pcMv = NULL; m_pcMvd = NULL; m_piRefIdx = NULL; m_uiNumPartition = 0; } // -------------------------------------------------------------------------------------------------------------------- // Clear / copy // -------------------------------------------------------------------------------------------------------------------- Void TComCUMvField::clearMvField() { for ( Int i = 0; i < m_uiNumPartition; i++ ) { m_pcMv [ i ].setZero(); m_pcMvd[ i ].setZero(); } assert( sizeof( *m_piRefIdx ) == 1 ); memset( m_piRefIdx, NOT_VALID, m_uiNumPartition * sizeof( *m_piRefIdx ) ); } Void TComCUMvField::copyFrom( TComCUMvField const * pcCUMvFieldSrc, Int iNumPartSrc, Int iPartAddrDst ) { Int iSizeInTComMv = sizeof( TComMv ) * iNumPartSrc; memcpy( m_pcMv + iPartAddrDst, pcCUMvFieldSrc->m_pcMv, iSizeInTComMv ); memcpy( m_pcMvd + iPartAddrDst, pcCUMvFieldSrc->m_pcMvd, iSizeInTComMv ); memcpy( m_piRefIdx + iPartAddrDst, pcCUMvFieldSrc->m_piRefIdx, sizeof( *m_piRefIdx ) * iNumPartSrc ); } Void TComCUMvField::copyTo( TComCUMvField* pcCUMvFieldDst, Int iPartAddrDst ) const { copyTo( pcCUMvFieldDst, iPartAddrDst, 0, m_uiNumPartition ); } Void TComCUMvField::copyTo( TComCUMvField* pcCUMvFieldDst, Int iPartAddrDst, UInt uiOffset, UInt uiNumPart ) const { Int iSizeInTComMv = sizeof( TComMv ) * uiNumPart; Int iOffset = uiOffset + iPartAddrDst; memcpy( pcCUMvFieldDst->m_pcMv + iOffset, m_pcMv + uiOffset, iSizeInTComMv ); memcpy( pcCUMvFieldDst->m_pcMvd + iOffset, m_pcMvd + uiOffset, iSizeInTComMv ); memcpy( pcCUMvFieldDst->m_piRefIdx + iOffset, m_piRefIdx + uiOffset, sizeof( *m_piRefIdx ) * uiNumPart ); } // -------------------------------------------------------------------------------------------------------------------- // Set // -------------------------------------------------------------------------------------------------------------------- template Void TComCUMvField::setAll( T *p, T const & val, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ) { Int i; p += iPartAddr; Int numElements = m_uiNumPartition >> ( 2 * uiDepth ); switch( eCUMode ) { case SIZE_2Nx2N: for ( i = 0; i < numElements; i++ ) { p[ i ] = val; } break; case SIZE_2NxN: numElements >>= 1; for ( i = 0; i < numElements; i++ ) { p[ i ] = val; } break; case SIZE_Nx2N: numElements >>= 2; for ( i = 0; i < numElements; i++ ) { p[ i ] = val; p[ i + 2 * numElements ] = val; } break; case SIZE_NxN: numElements >>= 2; for ( i = 0; i < numElements; i++) { p[ i ] = val; } break; case SIZE_2NxnU: { Int iCurrPartNumQ = numElements>>2; if( iPartIdx == 0 ) { T *pT = p; T *pT2 = p + iCurrPartNumQ; for (i = 0; i < (iCurrPartNumQ>>1); i++) { pT [i] = val; pT2[i] = val; } } else { T *pT = p; for (i = 0; i < (iCurrPartNumQ>>1); i++) { pT[i] = val; } pT = p + iCurrPartNumQ; for (i = 0; i < ( (iCurrPartNumQ>>1) + (iCurrPartNumQ<<1) ); i++) { pT[i] = val; } } break; } case SIZE_2NxnD: { Int iCurrPartNumQ = numElements>>2; if( iPartIdx == 0 ) { T *pT = p; for (i = 0; i < ( (iCurrPartNumQ>>1) + (iCurrPartNumQ<<1) ); i++) { pT[i] = val; } pT = p + ( numElements - iCurrPartNumQ ); for (i = 0; i < (iCurrPartNumQ>>1); i++) { pT[i] = val; } } else { T *pT = p; T *pT2 = p + iCurrPartNumQ; for (i = 0; i < (iCurrPartNumQ>>1); i++) { pT [i] = val; pT2[i] = val; } } break; } case SIZE_nLx2N: { Int iCurrPartNumQ = numElements>>2; if( iPartIdx == 0 ) { T *pT = p; T *pT2 = p + (iCurrPartNumQ<<1); T *pT3 = p + (iCurrPartNumQ>>1); T *pT4 = p + (iCurrPartNumQ<<1) + (iCurrPartNumQ>>1); for (i = 0; i < (iCurrPartNumQ>>2); i++) { pT [i] = val; pT2[i] = val; pT3[i] = val; pT4[i] = val; } } else { T *pT = p; T *pT2 = p + (iCurrPartNumQ<<1); for (i = 0; i < (iCurrPartNumQ>>2); i++) { pT [i] = val; pT2[i] = val; } pT = p + (iCurrPartNumQ>>1); pT2 = p + (iCurrPartNumQ<<1) + (iCurrPartNumQ>>1); for (i = 0; i < ( (iCurrPartNumQ>>2) + iCurrPartNumQ ); i++) { pT [i] = val; pT2[i] = val; } } break; } case SIZE_nRx2N: { Int iCurrPartNumQ = numElements>>2; if( iPartIdx == 0 ) { T *pT = p; T *pT2 = p + (iCurrPartNumQ<<1); for (i = 0; i < ( (iCurrPartNumQ>>2) + iCurrPartNumQ ); i++) { pT [i] = val; pT2[i] = val; } pT = p + iCurrPartNumQ + (iCurrPartNumQ>>1); pT2 = p + numElements - iCurrPartNumQ + (iCurrPartNumQ>>1); for (i = 0; i < (iCurrPartNumQ>>2); i++) { pT [i] = val; pT2[i] = val; } } else { T *pT = p; T *pT2 = p + (iCurrPartNumQ>>1); T *pT3 = p + (iCurrPartNumQ<<1); T *pT4 = p + (iCurrPartNumQ<<1) + (iCurrPartNumQ>>1); for (i = 0; i < (iCurrPartNumQ>>2); i++) { pT [i] = val; pT2[i] = val; pT3[i] = val; pT4[i] = val; } } break; } default: assert(0); break; } } Void TComCUMvField::setAllMv( TComMv const & mv, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ) { setAll(m_pcMv, mv, eCUMode, iPartAddr, uiDepth, iPartIdx); } Void TComCUMvField::setAllMvd( TComMv const & mvd, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ) { setAll(m_pcMvd, mvd, eCUMode, iPartAddr, uiDepth, iPartIdx); } Void TComCUMvField::setAllRefIdx ( Int iRefIdx, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ) { setAll(m_piRefIdx, static_cast(iRefIdx), eCUMode, iPartAddr, uiDepth, iPartIdx); } Void TComCUMvField::setAllMvField( TComMvField const & mvField, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ) { setAllMv ( mvField.getMv(), eCUMode, iPartAddr, uiDepth, iPartIdx ); setAllRefIdx( mvField.getRefIdx(), eCUMode, iPartAddr, uiDepth, iPartIdx ); } /**Subsampling of the stored prediction mode, reference index and motion vector * \param pePredMode Pointer to prediction modes * \param scale Factor by which to subsample motion information */ #if REDUCED_ENCODER_MEMORY Void TComCUMvField::compress(SChar *pePredMode, const SChar* pePredModeSource, const Int scale, const TComCUMvField &source) { const Int numSubpartsWithIdenticalMotion = scale * scale; assert( numSubpartsWithIdenticalMotion > 0 && numSubpartsWithIdenticalMotion <= m_uiNumPartition); assert(source.m_uiNumPartition == m_uiNumPartition); for ( Int partIdx = 0; partIdx < m_uiNumPartition; partIdx += numSubpartsWithIdenticalMotion ) { TComMv cMv(0,0); Int iRefIdx = 0; cMv = source.m_pcMv[ partIdx ]; PredMode predMode = static_cast( pePredModeSource[ partIdx ] ); iRefIdx = source.m_piRefIdx[ partIdx ]; for ( Int i = 0; i < numSubpartsWithIdenticalMotion; i++ ) { m_pcMv[ partIdx + i ] = cMv; pePredMode[ partIdx + i ] = predMode; m_piRefIdx[ partIdx + i ] = iRefIdx; } } } #else Void TComCUMvField::compress(SChar* pePredMode, Int scale) { Int N = scale * scale; assert( N > 0 && N <= m_uiNumPartition); for ( Int uiPartIdx = 0; uiPartIdx < m_uiNumPartition; uiPartIdx += N ) { TComMv cMv(0,0); Int iRefIdx = 0; cMv = m_pcMv[ uiPartIdx ]; PredMode predMode = static_cast( pePredMode[ uiPartIdx ] ); iRefIdx = m_piRefIdx[ uiPartIdx ]; for ( Int i = 0; i < N; i++ ) { m_pcMv[ uiPartIdx + i ] = cMv; pePredMode[ uiPartIdx + i ] = predMode; m_piRefIdx[ uiPartIdx + i ] = iRefIdx; } } } #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/TComMotionInfo.h000066400000000000000000000150571442026013100212770ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComMotionInfo.h \brief motion information handling classes (header) \todo TComMvField seems to be better to be inherited from TComMv */ #ifndef __TCOMMOTIONINFO__ #define __TCOMMOTIONINFO__ #include #include "CommonDef.h" #include "TComMv.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Type definition // ==================================================================================================================== /// parameters for AMVP typedef struct _AMVPInfo { TComMv m_acMvCand[ AMVP_MAX_NUM_CANDS ]; ///< array of motion vector predictor candidates Int iN; ///< number of motion vector predictor candidates #if MCTS_ENC_CHECK UInt numSpatialMVPCandidates; #endif } AMVPInfo; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// class for motion vector with reference index class TComMvField { private: TComMv m_acMv; Int m_iRefIdx; public: TComMvField() : m_iRefIdx( NOT_VALID ) {} Void setMvField( TComMv const & cMv, Int iRefIdx ) { m_acMv = cMv; m_iRefIdx = iRefIdx; } Void setRefIdx( Int refIdx ) { m_iRefIdx = refIdx; } TComMv const & getMv() const { return m_acMv; } TComMv & getMv() { return m_acMv; } Int getRefIdx() const { return m_iRefIdx; } Int getHor () const { return m_acMv.getHor(); } Int getVer () const { return m_acMv.getVer(); } }; /// class for motion information in one CU class TComCUMvField { private: TComMv* m_pcMv; TComMv* m_pcMvd; SChar* m_piRefIdx; UInt m_uiNumPartition; AMVPInfo m_cAMVPInfo; template Void setAll( T *p, T const & val, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx ); public: TComCUMvField() : m_pcMv(NULL), m_pcMvd(NULL), m_piRefIdx(NULL), m_uiNumPartition(0) {} ~TComCUMvField() {} // ------------------------------------------------------------------------------------------------------------------ // create / destroy // ------------------------------------------------------------------------------------------------------------------ Void create( UInt uiNumPartition ); Void destroy(); // ------------------------------------------------------------------------------------------------------------------ // clear / copy // ------------------------------------------------------------------------------------------------------------------ Void clearMvField(); Void copyFrom( TComCUMvField const * pcCUMvFieldSrc, Int iNumPartSrc, Int iPartAddrDst ); Void copyTo ( TComCUMvField* pcCUMvFieldDst, Int iPartAddrDst ) const; Void copyTo ( TComCUMvField* pcCUMvFieldDst, Int iPartAddrDst, UInt uiOffset, UInt uiNumPart ) const; // ------------------------------------------------------------------------------------------------------------------ // get // ------------------------------------------------------------------------------------------------------------------ TComMv const & getMv ( Int iIdx ) const { return m_pcMv [iIdx]; } TComMv const & getMvd ( Int iIdx ) const { return m_pcMvd [iIdx]; } Int getRefIdx( Int iIdx ) const { return m_piRefIdx[iIdx]; } AMVPInfo* getAMVPInfo () { return &m_cAMVPInfo; } // ------------------------------------------------------------------------------------------------------------------ // set // ------------------------------------------------------------------------------------------------------------------ Void setAllMv ( TComMv const & rcMv, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx=0 ); Void setAllMvd ( TComMv const & rcMvd, PartSize eCUMode, Int iPartAddr, UInt uiDepth, Int iPartIdx=0 ); Void setAllRefIdx ( Int iRefIdx, PartSize eMbMode, Int iPartAddr, UInt uiDepth, Int iPartIdx=0 ); Void setAllMvField( TComMvField const & mvField, PartSize eMbMode, Int iPartAddr, UInt uiDepth, Int iPartIdx=0 ); Void setNumPartition( Int iNumPart ) { m_uiNumPartition = iNumPart; } Void linkToWithOffset( TComCUMvField const * src, Int offset ) { m_pcMv = src->m_pcMv + offset; m_pcMvd = src->m_pcMvd + offset; m_piRefIdx = src->m_piRefIdx + offset; } #if REDUCED_ENCODER_MEMORY Void compress(SChar *pePredMode, const SChar* pePredModeSource, const Int scale, const TComCUMvField &source); #else Void compress(SChar* pePredMode, Int scale); #endif }; //! \} #endif // __TCOMMOTIONINFO__ HM-HM-18.0/source/Lib/TLibCommon/TComMv.h000066400000000000000000000131551442026013100175750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComMv.h \brief motion vector class (header) */ #ifndef __TCOMMV__ #define __TCOMMV__ #include "CommonDef.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// basic motion vector class class TComMv { private: Short m_iHor; ///< horizontal component of motion vector Short m_iVer; ///< vertical component of motion vector public: // ------------------------------------------------------------------------------------------------------------------ // constructors // ------------------------------------------------------------------------------------------------------------------ TComMv() : m_iHor(0), m_iVer(0) { } TComMv( Short iHor, Short iVer ) : m_iHor(iHor), m_iVer(iVer) { } // ------------------------------------------------------------------------------------------------------------------ // set // ------------------------------------------------------------------------------------------------------------------ Void set ( Short iHor, Short iVer) { m_iHor = iHor; m_iVer = iVer; } Void setHor ( Short i ) { m_iHor = i; } Void setVer ( Short i ) { m_iVer = i; } Void setZero () { m_iHor = m_iVer = 0; } // ------------------------------------------------------------------------------------------------------------------ // get // ------------------------------------------------------------------------------------------------------------------ Int getHor () const { return m_iHor; } Int getVer () const { return m_iVer; } Int getAbsHor () const { return abs( m_iHor ); } Int getAbsVer () const { return abs( m_iVer ); } // ------------------------------------------------------------------------------------------------------------------ // operations // ------------------------------------------------------------------------------------------------------------------ const TComMv& operator += (const TComMv& rcMv) { m_iHor += rcMv.m_iHor; m_iVer += rcMv.m_iVer; return *this; } const TComMv& operator-= (const TComMv& rcMv) { m_iHor -= rcMv.m_iHor; m_iVer -= rcMv.m_iVer; return *this; } #if !ME_ENABLE_ROUNDING_OF_MVS const TComMv& operator>>= (const Int i) { m_iHor >>= i; m_iVer >>= i; return *this; } #endif #if ME_ENABLE_ROUNDING_OF_MVS //! shift right with rounding Void divideByPowerOf2 (const Int i) { Int offset = (i == 0) ? 0 : 1 << (i - 1); m_iHor += offset; m_iVer += offset; m_iHor >>= i; m_iVer >>= i; } #endif const TComMv& operator<<= (const Int i) { m_iHor <<= i; m_iVer <<= i; return *this; } const TComMv operator - ( const TComMv& rcMv ) const { return TComMv( m_iHor - rcMv.m_iHor, m_iVer - rcMv.m_iVer ); } const TComMv operator + ( const TComMv& rcMv ) const { return TComMv( m_iHor + rcMv.m_iHor, m_iVer + rcMv.m_iVer ); } Bool operator== ( const TComMv& rcMv ) const { return (m_iHor==rcMv.m_iHor && m_iVer==rcMv.m_iVer); } Bool operator!= ( const TComMv& rcMv ) const { return (m_iHor!=rcMv.m_iHor || m_iVer!=rcMv.m_iVer); } const TComMv scaleMv( Int iScale ) const { Int mvx = Clip3( -32768, 32767, (iScale * getHor() + 127 + (iScale * getHor() < 0)) >> 8 ); Int mvy = Clip3( -32768, 32767, (iScale * getVer() + 127 + (iScale * getVer() < 0)) >> 8 ); return TComMv( mvx, mvy ); } };// END CLASS DEFINITION TComMV //! \} #endif // __TCOMMV__ HM-HM-18.0/source/Lib/TLibCommon/TComPattern.cpp000066400000000000000000000573441442026013100211730ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPattern.cpp \brief neighbouring pixel access classes */ #include "TComPic.h" #include "TComPattern.h" #include "TComDataCU.h" #include "TComTU.h" #include "Debug.h" #include "TComPrediction.h" //! \ingroup TLibCommon //! \{ // Forward declarations /// padding of unavailable reference samples for intra prediction Void fillReferenceSamples( const Int bitDepth, #if O0043_BEST_EFFORT_DECODING const Int bitDepthDelta, #endif const Pel* piRoiOrigin, Pel* piIntraTemp, const Bool* bNeighborFlags, const Int iNumIntraNeighbor, const Int unitWidth, const Int unitHeight, const Int iAboveUnits, const Int iLeftUnits, const UInt uiWidth, const UInt uiHeight, const Int iPicStride ); /// constrained intra prediction Bool isAboveLeftAvailable ( const TComDataCU* pcCU, UInt uiPartIdxLT ); Int isAboveAvailable ( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags ); Int isLeftAvailable ( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags ); Int isAboveRightAvailable ( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool* bValidFlags ); Int isBelowLeftAvailable ( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool* bValidFlags ); // ==================================================================================================================== // Public member functions (TComPattern) // ==================================================================================================================== #if MCTS_ENC_CHECK Void TComPattern::initPattern(Pel* piY, Int roiWidth, Int roiHeight, Int stride, Int bitDepthLuma, Int roiPosX, Int roiPosY) #else Void TComPattern::initPattern (Pel* piY, Int roiWidth, Int roiHeight, Int stride, Int bitDepthLuma) #endif { m_piROIOrigin = piY; m_roiWidth = roiWidth; m_roiHeight = roiHeight; m_patternStride = stride; m_bitDepth = bitDepthLuma; #if MCTS_ENC_CHECK m_roiPosX = roiPosX; m_roiPosY = roiPosY; #endif } #if MCTS_ENC_CHECK Void TComPattern::setTileBorders(Int tileLeftTopPelPosX, Int tileLeftTopPelPosY, Int tileRightBottomPelPosX, Int tileRightBottomPelPosY) { m_tileLeftTopPelPosX = tileLeftTopPelPosX; m_tileLeftTopPelPosY = tileLeftTopPelPosY; m_tileRightBottomPelPosX = tileRightBottomPelPosX; m_tileRightBottomPelPosY = tileRightBottomPelPosY; } #endif // TODO: move this function to TComPrediction.cpp. Void TComPrediction::initIntraPatternChType( TComTU &rTu, const ComponentID compID, const Bool bFilterRefSamples DEBUG_STRING_FN_DECLARE(sDebug)) { const ChannelType chType = toChannelType(compID); TComDataCU *pcCU=rTu.getCU(); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiZorderIdxInPart=rTu.GetAbsPartIdxTU(); const UInt uiTuWidth = rTu.getRect(compID).width; const UInt uiTuHeight = rTu.getRect(compID).height; const UInt uiTuWidth2 = uiTuWidth << 1; const UInt uiTuHeight2 = uiTuHeight << 1; const Int iBaseUnitSize = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); const Int iUnitWidth = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleX(compID); const Int iUnitHeight = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleY(compID); const Int iTUWidthInUnits = uiTuWidth / iUnitWidth; const Int iTUHeightInUnits = uiTuHeight / iUnitHeight; const Int iAboveUnits = iTUWidthInUnits << 1; const Int iLeftUnits = iTUHeightInUnits << 1; const Int bitDepthForChannel = sps.getBitDepth(chType); assert(iTUHeightInUnits > 0 && iTUWidthInUnits > 0); const Int iPartIdxStride = pcCU->getPic()->getNumPartInCtuWidth(); const UInt uiPartIdxLT = pcCU->getZorderIdxInCtu() + uiZorderIdxInPart; const UInt uiPartIdxRT = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + iTUWidthInUnits - 1 ]; const UInt uiPartIdxLB = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + ((iTUHeightInUnits - 1) * iPartIdxStride)]; Int iPicStride = pcCU->getPic()->getStride(compID); Bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; Int iNumIntraNeighbor = 0; bNeighborFlags[iLeftUnits] = isAboveLeftAvailable( pcCU, uiPartIdxLT ); iNumIntraNeighbor += bNeighborFlags[iLeftUnits] ? 1 : 0; iNumIntraNeighbor += isAboveAvailable ( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1) ); iNumIntraNeighbor += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1 + iTUWidthInUnits ) ); iNumIntraNeighbor += isLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1) ); iNumIntraNeighbor += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1 - iTUHeightInUnits) ); const UInt uiROIWidth = uiTuWidth2+1; const UInt uiROIHeight = uiTuHeight2+1; assert(uiROIWidth*uiROIHeight <= m_iYuvExtSize); #if DEBUG_STRING std::stringstream ss(stringstream::out); #endif { Pel *piIntraTemp = m_piYuvExt[compID][PRED_BUF_UNFILTERED]; Pel *piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiZorderIdxInPart); #if O0043_BEST_EFFORT_DECODING const Int bitDepthForChannelInStream = sps.getStreamBitDepth(chType); fillReferenceSamples (bitDepthForChannelInStream, bitDepthForChannelInStream - bitDepthForChannel, #else fillReferenceSamples (bitDepthForChannel, #endif piRoiOrigin, piIntraTemp, bNeighborFlags, iNumIntraNeighbor, iUnitWidth, iUnitHeight, iAboveUnits, iLeftUnits, uiROIWidth, uiROIHeight, iPicStride); #if DEBUG_STRING if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA)) { ss << "###: generating Ref Samples for channel " << compID << " and " << rTu.getRect(compID).width << " x " << rTu.getRect(compID).height << "\n"; for (UInt y=0; y> shift; } piSrcPtr -= stride * (uiTuHeight2 - 1); } else { for(UInt i=1; i> 2; } } //------------------------------------------------ //top-left if (useStrongIntraSmoothing) { *piDestPtr = piSrcPtr[0]; } else { *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[1] + 2 ) >> 2; } piDestPtr += 1; piSrcPtr += 1; //------------------------------------------------ //top row (left-to-right) if (useStrongIntraSmoothing) { const Int shift = g_aucConvertToBit[uiTuWidth] + 3; //log2(uiTuWidth2) for(UInt i=1; i> shift; } piSrcPtr += uiTuWidth2 - 1; } else { for(UInt i=1; i> 2; } } //------------------------------------------------ *piDestPtr=*piSrcPtr; // far right is not filtered #if DEBUG_STRING if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA)) { ss << "###: filtered result for channel " << compID <<"\n"; for (UInt y=0; y(iNext, iLeftUnits); // fill left column while (iCurrJnit < iNextOrTop) { for (i=0; i= iLeftUnits) ? unitWidth : unitHeight; const Pel refSample = *(piIntraLineCur-1); for (i=0; i= iLeftUnits) ? unitWidth : unitHeight; iCurrJnit++; } } // Copy processed samples piIntraLineTemp = piIntraLine + uiHeight + unitWidth - 2; // top left, top and top right samples for (i=0; i=4 && uiTuChHeight>=4 && uiTuChWidth<128 && uiTuChHeight<128); if (uiDirMode == DC_IDX) { bFilter=false; //no smoothing for DC or LM chroma } else { Int diff = min(abs((Int) uiDirMode - HOR_IDX), abs((Int)uiDirMode - VER_IDX)); UInt sizeIndex=g_aucConvertToBit[uiTuChWidth]; assert(sizeIndex < MAX_INTRA_FILTER_DEPTHS); bFilter = diff > m_aucIntraFilter[toChannelType(compID)][sizeIndex]; } } return bFilter; } Bool isAboveLeftAvailable( const TComDataCU* pcCU, UInt uiPartIdxLT ) { Bool bAboveLeftFlag; UInt uiPartAboveLeft; const TComDataCU* pcCUAboveLeft = pcCU->getPUAboveLeft( uiPartAboveLeft, uiPartIdxLT ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { bAboveLeftFlag = ( pcCUAboveLeft && pcCUAboveLeft->isIntra( uiPartAboveLeft ) ); } else { bAboveLeftFlag = (pcCUAboveLeft ? true : false); } return bAboveLeftFlag; } Int isAboveAvailable( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags ) { const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT]; const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxRT]+1; const UInt uiIdxStep = 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep ) { UInt uiPartAbove; const TComDataCU* pcCUAbove = pcCU->getPUAbove( uiPartAbove, g_auiRasterToZscan[uiRasterPart] ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUAbove && pcCUAbove->isIntra( uiPartAbove ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if (pcCUAbove) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags++; } return iNumIntra; } Int isLeftAvailable( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags ) { const UInt uiRasterPartBegin = g_auiZscanToRaster[uiPartIdxLT]; const UInt uiRasterPartEnd = g_auiZscanToRaster[uiPartIdxLB]+1; const UInt uiIdxStep = pcCU->getPic()->getNumPartInCtuWidth(); Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiRasterPart = uiRasterPartBegin; uiRasterPart < uiRasterPartEnd; uiRasterPart += uiIdxStep ) { UInt uiPartLeft; const TComDataCU* pcCULeft = pcCU->getPULeft( uiPartLeft, g_auiRasterToZscan[uiRasterPart] ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCULeft && pcCULeft->isIntra( uiPartLeft ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCULeft ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags--; // opposite direction } return iNumIntra; } Int isAboveRightAvailable( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxRT, Bool *bValidFlags ) { const UInt uiNumUnitsInPU = g_auiZscanToRaster[uiPartIdxRT] - g_auiZscanToRaster[uiPartIdxLT] + 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ ) { UInt uiPartAboveRight; const TComDataCU* pcCUAboveRight = pcCU->getPUAboveRight( uiPartAboveRight, uiPartIdxRT, uiOffset ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUAboveRight && pcCUAboveRight->isIntra( uiPartAboveRight ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCUAboveRight ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags++; } return iNumIntra; } Int isBelowLeftAvailable( const TComDataCU* pcCU, UInt uiPartIdxLT, UInt uiPartIdxLB, Bool *bValidFlags ) { const UInt uiNumUnitsInPU = (g_auiZscanToRaster[uiPartIdxLB] - g_auiZscanToRaster[uiPartIdxLT]) / pcCU->getPic()->getNumPartInCtuWidth() + 1; Bool *pbValidFlags = bValidFlags; Int iNumIntra = 0; for ( UInt uiOffset = 1; uiOffset <= uiNumUnitsInPU; uiOffset++ ) { UInt uiPartBelowLeft; const TComDataCU* pcCUBelowLeft = pcCU->getPUBelowLeft( uiPartBelowLeft, uiPartIdxLB, uiOffset ); if(pcCU->getSlice()->getPPS()->getConstrainedIntraPred()) { if ( pcCUBelowLeft && pcCUBelowLeft->isIntra( uiPartBelowLeft ) ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } else { if ( pcCUBelowLeft ) { iNumIntra++; *pbValidFlags = true; } else { *pbValidFlags = false; } } pbValidFlags--; // opposite direction } return iNumIntra; } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPattern.h000066400000000000000000000111231442026013100206210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPattern.h \brief neighbouring pixel access classes (header) */ #ifndef __TCOMPATTERN__ #define __TCOMPATTERN__ // Include files #include "CommonDef.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class TComDataCU; class TComTU; /// neighbouring pixel access class for all components class TComPattern { private: Pel* m_piROIOrigin; Int m_roiWidth; Int m_roiHeight; Int m_patternStride; Int m_bitDepth; #if MCTS_ENC_CHECK Int m_roiPosX; Int m_roiPosY; Int m_tileLeftTopPelPosX; Int m_tileLeftTopPelPosY; Int m_tileRightBottomPelPosX; Int m_tileRightBottomPelPosY; #endif public: // ROI & pattern information, (ROI = &pattern[AboveOffset][LeftOffset]) Int getROIYWidth() const { return m_roiWidth; } Int getROIYHeight() const { return m_roiHeight; } Int getPatternLStride() const { return m_patternStride; } Int getBitDepthY() const { return m_bitDepth; } #if MCTS_ENC_CHECK Int getROIYPosX() const { return m_roiPosX; } Int getROIYPosY() const { return m_roiPosY; } Int getTileLeftTopPelPosX() const { return m_tileLeftTopPelPosX; } Int getTileLeftTopPelPosY() const { return m_tileLeftTopPelPosY; } Int getTileRightBottomPelPosX() const { return m_tileRightBottomPelPosX; } Int getTileRightBottomPelPosY() const { return m_tileRightBottomPelPosY; } #endif __inline Pel* getROIY() { return m_piROIOrigin; } __inline const Pel* getROIY() const { return m_piROIOrigin; } TComPattern() : m_piROIOrigin(NULL) , m_roiWidth(0) , m_roiHeight(0) , m_patternStride(0) , m_bitDepth(0) #if MCTS_ENC_CHECK , m_roiPosX(0) , m_roiPosY(0) , m_tileLeftTopPelPosX(0) , m_tileLeftTopPelPosY(0) , m_tileRightBottomPelPosX(0) , m_tileRightBottomPelPosY(0) #endif {}; // ------------------------------------------------------------------------------------------------------------------- // initialization functions // ------------------------------------------------------------------------------------------------------------------- /// set parameters from Pel buffers for accessing neighbouring pixels #if MCTS_ENC_CHECK Void initPattern(Pel* piY, Int roiWidth, Int roiHeight, Int stride, Int bitDepthLuma, Int roiPosX, Int roiPosY); Void setTileBorders(Int tileLeftTopPelPosX, Int tileLeftTopPelPosY, Int tileRightBottomPelPosX, Int tileRightBottomPelPosY); #else Void initPattern(Pel* piY, Int roiWidth, Int roiHeight, Int stride, Int bitDepthLuma); #endif }; //! \} #endif // __TCOMPATTERN__ HM-HM-18.0/source/Lib/TLibCommon/TComPic.cpp000066400000000000000000000440551442026013100202640ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPic.cpp \brief picture class */ #include "TComPic.h" #include "SEI.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TComPic::TComPic() : m_uiTLayer (0) , m_bUsedByCurr (false) , m_bIsLongTerm (false) , m_pcPicYuvPred (NULL) , m_pcPicYuvResi (NULL) , m_bReconstructed (false) , m_bNeededForOutput (false) , m_uiCurrSliceIdx (0) , m_bCheckLTMSB (false) { for(UInt i=0; icreate( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); m_apcPicYuv[PIC_YUV_TRUE_ORG] = new TComPicYuv; m_apcPicYuv[PIC_YUV_TRUE_ORG]->create( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); } #if REDUCED_ENCODER_MEMORY if (bCreateForImmediateReconstruction) { #endif m_apcPicYuv[PIC_YUV_REC] = new TComPicYuv; m_apcPicYuv[PIC_YUV_REC]->create( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); #if SHUTTER_INTERVAL_SEI_PROCESSING if (bCreateForProcessedReconstruction) { m_apcPicYuv[PIC_YUV_POST_REC] = new TComPicYuv; m_apcPicYuv[PIC_YUV_POST_REC]->create(iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true); } #endif #if REDUCED_ENCODER_MEMORY } #endif #if JVET_X0048_X0103_FILM_GRAIN if (bCreateFilteredSourcePicYuv) { m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG] = new TComPicYuv; m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]->create(iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true); } #endif // there are no SEI messages associated with this picture initially if (m_SEIs.size() > 0) { deleteSEIs (m_SEIs); } m_bUsedByCurr = false; } #if REDUCED_ENCODER_MEMORY #if JVET_X0048_X0103_FILM_GRAIN Void TComPic::prepareForEncoderSourcePicYuv( const Bool bCreateFilteredSourcePicYuv ) #else Void TComPic::prepareForEncoderSourcePicYuv() #endif { const TComSPS &sps=m_picSym.getSPS(); const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc(); const Int iWidth = sps.getPicWidthInLumaSamples(); const Int iHeight = sps.getPicHeightInLumaSamples(); const UInt uiMaxCuWidth = sps.getMaxCUWidth(); const UInt uiMaxCuHeight = sps.getMaxCUHeight(); const UInt uiMaxDepth = sps.getMaxTotalCUDepth(); if (m_apcPicYuv[PIC_YUV_ORG ]==NULL) { m_apcPicYuv[PIC_YUV_ORG ] = new TComPicYuv; m_apcPicYuv[PIC_YUV_ORG ]->create( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); } if (m_apcPicYuv[PIC_YUV_TRUE_ORG ]==NULL) { m_apcPicYuv[PIC_YUV_TRUE_ORG] = new TComPicYuv; m_apcPicYuv[PIC_YUV_TRUE_ORG]->create( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); } #if JVET_X0048_X0103_FILM_GRAIN if (m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG] == NULL && bCreateFilteredSourcePicYuv) { m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG] = new TComPicYuv; m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]->create(iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true); } #endif } #if SHUTTER_INTERVAL_SEI_PROCESSING Void TComPic::prepareForReconstruction( const Bool bCreateForProcessedReconstruction ) #else Void TComPic::prepareForReconstruction() #endif { if (m_apcPicYuv[PIC_YUV_REC] == NULL) { const TComSPS &sps=m_picSym.getSPS(); const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc(); const Int iWidth = sps.getPicWidthInLumaSamples(); const Int iHeight = sps.getPicHeightInLumaSamples(); const UInt uiMaxCuWidth = sps.getMaxCUWidth(); const UInt uiMaxCuHeight = sps.getMaxCUHeight(); const UInt uiMaxDepth = sps.getMaxTotalCUDepth(); m_apcPicYuv[PIC_YUV_REC] = new TComPicYuv; m_apcPicYuv[PIC_YUV_REC]->create( iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true ); } // mark it should be extended m_apcPicYuv[PIC_YUV_REC]->setBorderExtension(false); #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_apcPicYuv[PIC_YUV_POST_REC] == NULL && bCreateForProcessedReconstruction) { const TComSPS &sps = m_picSym.getSPS(); const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc(); const Int iWidth = sps.getPicWidthInLumaSamples(); const Int iHeight = sps.getPicHeightInLumaSamples(); const UInt uiMaxCuWidth = sps.getMaxCUWidth(); const UInt uiMaxCuHeight = sps.getMaxCUHeight(); const UInt uiMaxDepth = sps.getMaxTotalCUDepth(); m_apcPicYuv[PIC_YUV_POST_REC] = new TComPicYuv; m_apcPicYuv[PIC_YUV_POST_REC]->create(iWidth, iHeight, chromaFormatIDC, uiMaxCuWidth, uiMaxCuHeight, uiMaxDepth, true); } // mark it should be extended if (bCreateForProcessedReconstruction) { m_apcPicYuv[PIC_YUV_POST_REC]->setBorderExtension(false); } #endif m_picSym.prepareForReconstruction(); } Void TComPic::releaseReconstructionIntermediateData() { m_picSym.releaseReconstructionIntermediateData(); } Void TComPic::releaseEncoderSourceImageData() { if (m_apcPicYuv[PIC_YUV_ORG ]) { m_apcPicYuv[PIC_YUV_ORG]->destroy(); delete m_apcPicYuv[PIC_YUV_ORG]; m_apcPicYuv[PIC_YUV_ORG] = NULL; } if (m_apcPicYuv[PIC_YUV_TRUE_ORG ]) { m_apcPicYuv[PIC_YUV_TRUE_ORG]->destroy(); delete m_apcPicYuv[PIC_YUV_TRUE_ORG]; m_apcPicYuv[PIC_YUV_TRUE_ORG] = NULL; } #if JVET_X0048_X0103_FILM_GRAIN if (m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]) { m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]->destroy(); delete m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]; m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG] = NULL; } #endif } Void TComPic::releaseAllReconstructionData() { #if SHUTTER_INTERVAL_SEI_PROCESSING if (m_apcPicYuv[PIC_YUV_POST_REC]) { m_apcPicYuv[PIC_YUV_POST_REC]->destroy(); delete m_apcPicYuv[PIC_YUV_POST_REC]; m_apcPicYuv[PIC_YUV_POST_REC] = NULL; } #endif if (m_apcPicYuv[PIC_YUV_REC ]) { m_apcPicYuv[PIC_YUV_REC]->destroy(); delete m_apcPicYuv[PIC_YUV_REC]; m_apcPicYuv[PIC_YUV_REC] = NULL; } m_picSym.releaseAllReconstructionData(); } #endif Void TComPic::destroy() { m_picSym.destroy(); for(UInt i=0; idestroy(); delete m_apcPicYuv[i]; m_apcPicYuv[i] = NULL; } } deleteSEIs(m_SEIs); #if JVET_X0048_X0103_FILM_GRAIN m_grainBuf = NULL; #endif } Void TComPic::compressMotion() { TComPicSym* pPicSym = getPicSym(); for ( UInt uiCUAddr = 0; uiCUAddr < pPicSym->getNumberOfCtusInFrame(); uiCUAddr++ ) { TComDataCU* pCtu = pPicSym->getCtu(uiCUAddr); pCtu->compressMV(); } } Bool TComPic::getSAOMergeAvailability(Int currAddr, Int mergeAddr) { Bool mergeCtbInSliceSeg = (mergeAddr >= getPicSym()->getCtuTsToRsAddrMap(getCtu(currAddr)->getSlice()->getSliceCurStartCtuTsAddr())); Bool mergeCtbInTile = (getPicSym()->getTileIdxMap(mergeAddr) == getPicSym()->getTileIdxMap(currAddr)); return (mergeCtbInSliceSeg && mergeCtbInTile); } UInt TComPic::getSubstreamForCtuAddr(const UInt ctuAddr, const Bool bAddressInRaster, TComSlice *pcSlice) { UInt subStrm; const bool bWPPEnabled=pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag(); const TComPicSym &picSym = *(getPicSym()); if ((bWPPEnabled && picSym.getFrameHeightInCtus()>1) || (picSym.getNumTiles()>1)) // wavefronts, and possibly tiles being used. { if (bWPPEnabled) { const UInt ctuRsAddr = bAddressInRaster?ctuAddr : picSym.getCtuTsToRsAddrMap(ctuAddr); const UInt frameWidthInCtus = picSym.getFrameWidthInCtus(); const UInt tileIndex = picSym.getTileIdxMap(ctuRsAddr); const UInt numTileColumns = (picSym.getNumTileColumnsMinus1()+1); const TComTile *pTile = picSym.getTComTile(tileIndex); const UInt firstCtuRsAddrOfTile = pTile->getFirstCtuRsAddr(); const UInt tileYInCtus = firstCtuRsAddrOfTile / frameWidthInCtus; // independent tiles => substreams are "per tile" const UInt ctuLine = ctuRsAddr / frameWidthInCtus; const UInt startingSubstreamForTile =(tileYInCtus*numTileColumns) + (pTile->getTileHeightInCtus()*(tileIndex%numTileColumns)); subStrm = startingSubstreamForTile + (ctuLine - tileYInCtus); } else { const UInt ctuRsAddr = bAddressInRaster?ctuAddr : picSym.getCtuTsToRsAddrMap(ctuAddr); const UInt tileIndex = picSym.getTileIdxMap(ctuRsAddr); subStrm=tileIndex; } } else { // dependent tiles => substreams are "per frame". subStrm = 0; } return subStrm; } #if JVET_X0048_X0103_FILM_GRAIN // initialization of frequency based film grain syntheis buffers and parameters void TComPic::createGrainSynthesizer(Bool bFirstPictureInSequence, SEIFilmGrainSynthesizer* pGrainCharacteristics, TComPicYuv* pGrainBuf, const TComSPS* sps) { m_grainCharacteristic = pGrainCharacteristics; m_grainBuf = pGrainBuf; Int width = sps->getPicWidthInLumaSamples(); Int height = sps->getPicHeightInLumaSamples(); ChromaFormat fmt = sps->getChromaFormatIdc(); Int bitDepth = sps->getBitDepth(CHANNEL_TYPE_LUMA); // Padding to make wd and ht multiple of max fgs window size(64) int paddedWdFGS = ((width - 1) | 0x3F) + 1 - width; int paddedHtFGS = ((height - 1) | 0x3F) + 1 - height; m_padValue = (paddedWdFGS > paddedHtFGS) ? paddedWdFGS : paddedHtFGS; if (bFirstPictureInSequence) { // Create and initialize the Film Grain Synthesizer m_grainCharacteristic->create(width, height, fmt, bitDepth, 1); //Frame level TComPicYuv buffer created to blend Film Grain Noise into it m_grainBuf->createWithPadding(width, height, fmt, true, true, m_padValue, m_padValue); m_grainCharacteristic->fgsInit(); } } TComPicYuv* TComPic::getPicYuvDisp() { Int payloadType = 0; std::list::iterator message; for (message = m_SEIs.begin(); message != m_SEIs.end(); ++message) { payloadType = (*message)->payloadType(); if (payloadType == SEI::FILM_GRAIN_CHARACTERISTICS) { m_grainCharacteristic->m_errorCode = -1; *m_grainCharacteristic->m_fgcParameters = *static_cast(*message); /* Validation of Film grain characteristic parameters for the constrains of SMPTE-RDD5*/ m_grainCharacteristic->m_errorCode = m_grainCharacteristic->grainValidateParams(); break; } } if (FGS_SUCCESS == m_grainCharacteristic->m_errorCode) { m_apcPicYuv[PIC_YUV_REC]->copyToPic(m_grainBuf); m_grainBuf->extendPicBorder(); // Padding to make wd and ht multiple of max fgs window size(64) m_grainCharacteristic->m_poc = getPOC(); m_grainCharacteristic->grainSynthesizeAndBlend(m_grainBuf, getSlice(0)->getIdrPicFlag()); return m_grainBuf; } else { if (payloadType == SEI::FILM_GRAIN_CHARACTERISTICS) { fprintf(stdout, "Film Grain synthesis is not performed. Error code: 0x%x \n", m_grainCharacteristic->m_errorCode); } return m_apcPicYuv[PIC_YUV_REC]; } } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING TComPic* TComPic::findPrevPicPOC(TComPic* pcPic, TComList* pcListPic) { TComPic* prevPic = NULL; TComPic* listPic = NULL; TComList::iterator iterListPic = pcListPic->begin(); for (Int i = 0; i < (Int)(pcListPic->size()); i++) { listPic = *(iterListPic); listPic->setCurrSliceIdx(0); if (listPic->getPOC() == pcPic->getPOC() - 1) { prevPic = *(iterListPic); prevPic->setCurrSliceIdx(0); } iterListPic++; } return prevPic; } Void TComPic::xOutputPostFilteredPic(TComPic* pcPic, TComList* pcListPic) { if (pcPic->getPOC() % 2 == 0) { TComPic* prevPic = findPrevPicPOC(pcPic, pcListPic); if (prevPic) { TComPicYuv* currYuv = pcPic->getPicYuvRec(); TComPicYuv* prevYuv = prevPic->getPicYuvRec(); TComPicYuv* postYuv = pcPic->getPicYuvPostRec(); for (Int chan = 0; chan < currYuv->getNumberValidComponents(); chan++) { const ComponentID ch = ComponentID(chan); const ChannelType cType = (ch == COMPONENT_Y) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA; const Int bitDepth = pcPic->getSlice(0)->getSPS()->getBitDepth(cType); const Int maxOutputValue = (1 << bitDepth) - 1; Pel* currPxl = currYuv->getAddr(ch); Pel* prevPxl = prevYuv->getAddr(ch); Pel* postPxl = postYuv->getAddr(ch); Int iStride = currYuv->getStride(ch); Int iHeight = currYuv->getHeight(ch); Int iWidth = currYuv->getWidth(ch); for (Int y = 0; y < iHeight; y++) { for (Int x = 0; x < iWidth; x++) { postPxl[x] = std::min(maxOutputValue, std::max(0, (currPxl[x] << 1) - prevPxl[x])); } currPxl += iStride; prevPxl += iStride; postPxl += iStride; } } } else { pcPic->getPicYuvRec()->copyToPic(pcPic->getPicYuvPostRec()); } } else { pcPic->getPicYuvRec()->copyToPic(pcPic->getPicYuvPostRec()); } } Void TComPic::xOutputPreFilteredPic(TComPic* pcPic, TComList* pcListPic) { if (pcPic->getPOC() % 2 == 0) { TComPic* prevPic = findPrevPicPOC(pcPic, pcListPic); if (prevPic) { TComPicYuv* currYuv = pcPic->getPicYuvOrg(); TComPicYuv* prevYuv = prevPic->getPicYuvOrg(); for (Int chan = 0; chan < currYuv->getNumberValidComponents(); chan++) { const ComponentID ch = ComponentID(chan); const ChannelType cType = (ch == COMPONENT_Y) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA; const Int bitDepth = pcPic->getSlice(0)->getSPS()->getBitDepth(cType); const Int maxOutputValue = (1 << bitDepth) - 1; Pel* currPxl = currYuv->getAddr(ch); Pel* prevPxl = prevYuv->getAddr(ch); Int iStride = currYuv->getStride(ch); Int iHeight = currYuv->getHeight(ch); Int iWidth = currYuv->getWidth(ch); for (Int y = 0; y < iHeight; y++) { for (Int x = 0; x < iWidth; x++) { currPxl[x] = std::min( maxOutputValue, std::max( 0, (currPxl[x] + prevPxl[x]) >> 1) ); } currPxl += iStride; prevPxl += iStride; } } } } } #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPic.h000066400000000000000000000262141442026013100177260ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPic.h \brief picture class (header) */ #ifndef __TCOMPIC__ #define __TCOMPIC__ // Include files #include "CommonDef.h" #include "TComPicSym.h" #include "TComPicYuv.h" #include "TComBitStream.h" #if JVET_X0048_X0103_FILM_GRAIN #include "SEIFilmGrainSynthesizer.h" #endif //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// picture class (symbol + YUV buffers) class TComPic { public: #if SHUTTER_INTERVAL_SEI_PROCESSING #if JVET_X0048_X0103_FILM_GRAIN typedef enum { PIC_YUV_ORG = 0, PIC_YUV_REC = 1, PIC_YUV_TRUE_ORG = 2, PIC_YUV_POST_REC = 3, PIC_FILTERED_ORIGINAL_FG = 4, NUM_PIC_YUV = 5} PIC_YUV_T; TComPicYuv* getPicFilteredFG() { return m_apcPicYuv[PIC_FILTERED_ORIGINAL_FG]; } #else typedef enum { PIC_YUV_ORG = 0, PIC_YUV_REC = 1, PIC_YUV_TRUE_ORG = 2, PIC_YUV_POST_REC = 3, NUM_PIC_YUV = 4 } PIC_YUV_T; #endif TComPicYuv* getPicYuvPostRec() { return m_apcPicYuv[PIC_YUV_POST_REC]; } TComPic* findPrevPicPOC(TComPic* pcPic, TComList* pcListPic); Void xOutputPostFilteredPic(TComPic* pcPic, TComList* pcListPic); Void xOutputPreFilteredPic(TComPic* pcPic, TComList* pcListPic); #else typedef enum { PIC_YUV_ORG=0, PIC_YUV_REC=1, PIC_YUV_TRUE_ORG=2, NUM_PIC_YUV=3 } PIC_YUV_T; #endif // TRUE_ORG is the input file without any pre-encoder colour space conversion (but with possible bit depth increment) TComPicYuv* getPicYuvTrueOrg() { return m_apcPicYuv[PIC_YUV_TRUE_ORG]; } private: UInt m_uiTLayer; // Temporal layer Bool m_bUsedByCurr; // Used by current picture Bool m_bIsLongTerm; // IS long term picture TComPicSym m_picSym; // Symbol TComPicYuv* m_apcPicYuv[NUM_PIC_YUV]; TComPicYuv* m_pcPicYuvPred; // Prediction TComPicYuv* m_pcPicYuvResi; // Residual Bool m_bReconstructed; Bool m_bNeededForOutput; UInt m_uiCurrSliceIdx; // Index of current slice Bool m_bCheckLTMSB; Bool m_isTop; Bool m_isField; std::vector > m_vSliceCUDataLink; SEIMessages m_SEIs; ///< Any SEI messages that have been received. If !NULL we own the object. public: TComPic(); virtual ~TComPic(); #if REDUCED_ENCODER_MEMORY Void create( const TComSPS &sps, const TComPPS &pps, const Bool bCreateEncoderSourcePicYuv, const Bool bCreateForImmediateReconstruction #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ); #if JVET_X0048_X0103_FILM_GRAIN Void prepareForEncoderSourcePicYuv( const Bool bCreateFilteredSourcePicYuv ); #else Void prepareForEncoderSourcePicYuv(); #endif #if SHUTTER_INTERVAL_SEI_PROCESSING Void prepareForReconstruction( const Bool bCreateForProcessedReconstruction ); #else Void prepareForReconstruction(); #endif Void releaseReconstructionIntermediateData(); Void releaseAllReconstructionData(); Void releaseEncoderSourceImageData(); #else Void create( const TComSPS &sps, const TComPPS &pps, const Bool bIsVirtual /*= false*/ #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ); #endif virtual Void destroy(); UInt getTLayer() const { return m_uiTLayer; } Void setTLayer( UInt uiTLayer ) { m_uiTLayer = uiTLayer; } Bool getUsedByCurr() const { return m_bUsedByCurr; } Void setUsedByCurr( Bool bUsed ) { m_bUsedByCurr = bUsed; } Bool getIsLongTerm() const { return m_bIsLongTerm; } Void setIsLongTerm( Bool lt ) { m_bIsLongTerm = lt; } Void setCheckLTMSBPresent (Bool b ) {m_bCheckLTMSB=b;} Bool getCheckLTMSBPresent () { return m_bCheckLTMSB;} TComPicSym* getPicSym() { return &m_picSym; } const TComPicSym* getPicSym() const { return &m_picSym; } TComSlice* getSlice(Int i) { return m_picSym.getSlice(i); } const TComSlice* getSlice(Int i) const { return m_picSym.getSlice(i); } Int getPOC() const { return m_picSym.getSlice(m_uiCurrSliceIdx)->getPOC(); } TComDataCU* getCtu( UInt ctuRsAddr ) { return m_picSym.getCtu( ctuRsAddr ); } const TComDataCU* getCtu( UInt ctuRsAddr ) const { return m_picSym.getCtu( ctuRsAddr ); } TComPicYuv* getPicYuvOrg() { return m_apcPicYuv[PIC_YUV_ORG]; } TComPicYuv* getPicYuvRec() { return m_apcPicYuv[PIC_YUV_REC]; } #if JVET_X0048_X0103_FILM_GRAIN Void createGrainSynthesizer(Bool bFirstPictureInSequence, SEIFilmGrainSynthesizer* pGrainCharacteristics, TComPicYuv* pGrainBuf, const TComSPS* sps); Int m_padValue; Bool m_isMctfFiltered; SEIFilmGrainSynthesizer *m_grainCharacteristic; TComPicYuv *m_grainBuf; TComPicYuv* getPicYuvDisp(); #endif TComPicYuv* getPicYuvPred() { return m_pcPicYuvPred; } TComPicYuv* getPicYuvResi() { return m_pcPicYuvResi; } Void setPicYuvPred( TComPicYuv* pcPicYuv ) { m_pcPicYuvPred = pcPicYuv; } Void setPicYuvResi( TComPicYuv* pcPicYuv ) { m_pcPicYuvResi = pcPicYuv; } UInt getNumberOfCtusInFrame() const { return m_picSym.getNumberOfCtusInFrame(); } UInt getNumPartInCtuWidth() const { return m_picSym.getNumPartInCtuWidth(); } UInt getNumPartInCtuHeight() const { return m_picSym.getNumPartInCtuHeight(); } UInt getNumPartitionsInCtu() const { return m_picSym.getNumPartitionsInCtu(); } UInt getFrameWidthInCtus() const { return m_picSym.getFrameWidthInCtus(); } UInt getFrameHeightInCtus() const { return m_picSym.getFrameHeightInCtus(); } UInt getMinCUWidth() const { return m_picSym.getMinCUWidth(); } UInt getMinCUHeight() const { return m_picSym.getMinCUHeight(); } Int getStride(const ComponentID id) const { return m_apcPicYuv[PIC_YUV_REC]->getStride(id); } Int getComponentScaleX(const ComponentID id) const { return m_apcPicYuv[PIC_YUV_REC]->getComponentScaleX(id); } Int getComponentScaleY(const ComponentID id) const { return m_apcPicYuv[PIC_YUV_REC]->getComponentScaleY(id); } ChromaFormat getChromaFormat() const { return m_apcPicYuv[PIC_YUV_REC]->getChromaFormat(); } Int getNumberValidComponents() const { return m_apcPicYuv[PIC_YUV_REC]->getNumberValidComponents(); } Void setReconMark (Bool b) { m_bReconstructed = b; } Bool getReconMark () const { return m_bReconstructed; } Void setOutputMark (Bool b) { m_bNeededForOutput = b; } Bool getOutputMark () const { return m_bNeededForOutput; } Void compressMotion(); UInt getCurrSliceIdx() const { return m_uiCurrSliceIdx; } Void setCurrSliceIdx(UInt i) { m_uiCurrSliceIdx = i; } UInt getNumAllocatedSlice() const {return m_picSym.getNumAllocatedSlice();} Void allocateNewSlice() {m_picSym.allocateNewSlice(); } Void clearSliceBuffer() {m_picSym.clearSliceBuffer(); } const Window& getConformanceWindow() const { return m_picSym.getSPS().getConformanceWindow(); } Window getDefDisplayWindow() const { return m_picSym.getSPS().getVuiParametersPresentFlag() ? m_picSym.getSPS().getVuiParameters()->getDefaultDisplayWindow() : Window(); } Bool getSAOMergeAvailability(Int currAddr, Int mergeAddr); UInt getSubstreamForCtuAddr(const UInt ctuAddr, const Bool bAddressInRaster, TComSlice *pcSlice); /* field coding parameters*/ Void setTopField(Bool b) {m_isTop = b;} Bool isTopField() {return m_isTop;} Void setField(Bool b) {m_isField = b;} Bool isField() const {return m_isField;} /** transfer ownership of seis to this picture */ Void setSEIs(SEIMessages& seis) { m_SEIs = seis; } /** * return the current list of SEI messages associated with this picture. * Pointer is valid until this->destroy() is called */ SEIMessages& getSEIs() { return m_SEIs; } /** * return the current list of SEI messages associated with this picture. * Pointer is valid until this->destroy() is called */ const SEIMessages& getSEIs() const { return m_SEIs; } };// END CLASS DEFINITION TComPic //! \} #endif // __TCOMPIC__ HM-HM-18.0/source/Lib/TLibCommon/TComPicSym.cpp000066400000000000000000000521671442026013100207600ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPicSym.cpp \brief picture symbol class */ #include "TComPicSym.h" #include "TComSampleAdaptiveOffset.h" #include "TComSlice.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TComPicSym::TComPicSym() :m_frameWidthInCtus(0) ,m_frameHeightInCtus(0) ,m_uiMinCUWidth(0) ,m_uiMinCUHeight(0) ,m_uhTotalDepth(0) ,m_numPartitionsInCtu(0) ,m_numPartInCtuWidth(0) ,m_numPartInCtuHeight(0) ,m_numCtusInFrame(0) ,m_apSlices() ,m_pictureCtuArray(NULL) ,m_numTileColumnsMinus1(0) ,m_numTileRowsMinus1(0) ,m_ctuTsToRsAddrMap(NULL) ,m_puiTileIdxMap(NULL) ,m_ctuRsToTsAddrMap(NULL) #if REDUCED_ENCODER_MEMORY ,m_dpbPerCtuData(NULL) #endif ,m_saoBlkParams(NULL) #if ADAPTIVE_QP_SELECTION ,m_pParentARLBuffer(NULL) #endif {} TComPicSym::~TComPicSym() { destroy(); } #if REDUCED_ENCODER_MEMORY Void TComPicSym::create ( const TComSPS &sps, const TComPPS &pps, UInt uiMaxDepth, const Bool bAllocateCtuArray ) #else Void TComPicSym::create ( const TComSPS &sps, const TComPPS &pps, UInt uiMaxDepth ) #endif { destroy(); m_sps = sps; m_pps = pps; #if !REDUCED_ENCODER_MEMORY const ChromaFormat chromaFormatIDC = sps.getChromaFormatIdc(); #endif const Int iPicWidth = sps.getPicWidthInLumaSamples(); const Int iPicHeight = sps.getPicHeightInLumaSamples(); const UInt uiMaxCuWidth = sps.getMaxCUWidth(); const UInt uiMaxCuHeight = sps.getMaxCUHeight(); m_uhTotalDepth = uiMaxDepth; m_numPartitionsInCtu = 1<<(m_uhTotalDepth<<1); m_uiMinCUWidth = uiMaxCuWidth >> m_uhTotalDepth; m_uiMinCUHeight = uiMaxCuHeight >> m_uhTotalDepth; m_numPartInCtuWidth = uiMaxCuWidth / m_uiMinCUWidth; // equivalent to 1<create( chromaFormatIDC, m_numPartitionsInCtu, uiMaxCuWidth, uiMaxCuHeight, false, uiMaxCuWidth >> m_uhTotalDepth #if ADAPTIVE_QP_SELECTION , m_pParentARLBuffer #endif ); } #endif m_ctuTsToRsAddrMap = new UInt[m_numCtusInFrame+1]; m_puiTileIdxMap = new UInt[m_numCtusInFrame]; m_ctuRsToTsAddrMap = new UInt[m_numCtusInFrame+1]; for(UInt i=0; icreate( chromaFormatIDC, m_numPartitionsInCtu, uiMaxCuWidth, uiMaxCuHeight, false, uiMaxCuWidth >> m_uhTotalDepth #if ADAPTIVE_QP_SELECTION , m_pParentARLBuffer #endif ); } } if (m_dpbPerCtuData == NULL) { m_dpbPerCtuData = new DPBPerCtuData[m_numCtusInFrame]; for(UInt i=0; idestroy(); delete m_pictureCtuArray[i]; m_pictureCtuArray[i] = NULL; } } delete [] m_pictureCtuArray; m_pictureCtuArray = NULL; } } Void TComPicSym::releaseAllReconstructionData() { releaseReconstructionIntermediateData(); if (m_dpbPerCtuData != NULL) { for(UInt i=0; idestroy(); delete m_pictureCtuArray[i]; m_pictureCtuArray[i] = NULL; } } delete [] m_pictureCtuArray; m_pictureCtuArray = NULL; } #endif delete [] m_ctuTsToRsAddrMap; m_ctuTsToRsAddrMap = NULL; delete [] m_puiTileIdxMap; m_puiTileIdxMap = NULL; delete [] m_ctuRsToTsAddrMap; m_ctuRsToTsAddrMap = NULL; if(m_saoBlkParams) { delete[] m_saoBlkParams; m_saoBlkParams = NULL; } #if ADAPTIVE_QP_SELECTION delete [] m_pParentARLBuffer; m_pParentARLBuffer = NULL; #endif } Void TComPicSym::allocateNewSlice() { m_apSlices.push_back(new TComSlice); m_apSlices.back()->setPPS(&m_pps); m_apSlices.back()->setSPS(&m_sps); if (m_apSlices.size()>=2) { m_apSlices.back()->copySliceInfo( m_apSlices[m_apSlices.size()-2] ); m_apSlices.back()->initSlice(); } } Void TComPicSym::clearSliceBuffer() { for (UInt i = 0; i < UInt(m_apSlices.size()); i++) { delete m_apSlices[i]; } m_apSlices.clear(); } Void TComPicSym::xInitCtuTsRsAddrMaps() { //generate the Coding Order Map and Inverse Coding Order Map for(Int ctuTsAddr=0, ctuRsAddr=0; ctuTsAddrgetGeneralPTL()->getProfileIdc(); if ( profileIdc == Profile::MAIN || profileIdc == Profile::MAIN10) //TODO: add more profiles to the tile-size check... { if (m_pps.getTilesEnabledFlag()) { minHeight = 64 / m_sps.getMaxCUHeight(); minWidth = 256 / m_sps.getMaxCUWidth(); } } for(Int row=0; row < numRows; row++) { for(Int col=0; col < numCols; col++) { const Int tileIdx = row * numCols + col; assert (m_tileParameters[tileIdx].getTileWidthInCtus() >= minWidth); assert (m_tileParameters[tileIdx].getTileHeightInCtus() >= minHeight); } } //initialize each tile of the current picture for( Int row=0; row < numRows; row++ ) { for( Int col=0; col < numCols; col++ ) { const Int tileIdx = row * numCols + col; //initialize the RightEdgePosInCU for each tile Int rightEdgePosInCTU = 0; for( Int i=0; i <= col; i++ ) { rightEdgePosInCTU += m_tileParameters[row * numCols + i].getTileWidthInCtus(); } m_tileParameters[tileIdx].setRightEdgePosInCtus(rightEdgePosInCTU-1); //initialize the BottomEdgePosInCU for each tile Int bottomEdgePosInCTU = 0; for( Int i=0; i <= row; i++ ) { bottomEdgePosInCTU += m_tileParameters[i * numCols + col].getTileHeightInCtus(); } m_tileParameters[tileIdx].setBottomEdgePosInCtus(bottomEdgePosInCTU-1); //initialize the FirstCUAddr for each tile m_tileParameters[tileIdx].setFirstCtuRsAddr( (m_tileParameters[tileIdx].getBottomEdgePosInCtus() - m_tileParameters[tileIdx].getTileHeightInCtus() + 1) * getFrameWidthInCtus() + m_tileParameters[tileIdx].getRightEdgePosInCtus() - m_tileParameters[tileIdx].getTileWidthInCtus() + 1); } } Int columnIdx = 0; Int rowIdx = 0; //initialize the TileIdxMap for( Int i=0; igetRightEdgePosInCtus() && currCtuRsAddr / m_frameWidthInCtus == getTComTile(uiTileIdx)->getBottomEdgePosInCtus() ) //the current CTU is the last CTU of the tile { if(uiTileIdx+1 == getNumTiles()) { nextCtuRsAddr = m_numCtusInFrame; } else { nextCtuRsAddr = getTComTile(uiTileIdx+1)->getFirstCtuRsAddr(); } } else //the current CTU is not the last CTU of the tile { if( currCtuRsAddr % m_frameWidthInCtus == getTComTile(uiTileIdx)->getRightEdgePosInCtus() ) //the current CTU is on the rightmost edge of the tile { nextCtuRsAddr = currCtuRsAddr + m_frameWidthInCtus - getTComTile(uiTileIdx)->getTileWidthInCtus() + 1; } else { nextCtuRsAddr = currCtuRsAddr + 1; } } return nextCtuRsAddr; } Void TComPicSym::deriveLoopFilterBoundaryAvailibility(Int ctuRsAddr, Bool& isLeftAvail, Bool& isRightAvail, Bool& isAboveAvail, Bool& isBelowAvail, Bool& isAboveLeftAvail, Bool& isAboveRightAvail, Bool& isBelowLeftAvail, Bool& isBelowRightAvail ) { isLeftAvail = (ctuRsAddr % m_frameWidthInCtus != 0); isRightAvail = (ctuRsAddr % m_frameWidthInCtus != m_frameWidthInCtus-1); isAboveAvail = (ctuRsAddr >= m_frameWidthInCtus ); isBelowAvail = (ctuRsAddr < m_numCtusInFrame - m_frameWidthInCtus); isAboveLeftAvail = (isAboveAvail && isLeftAvail); isAboveRightAvail= (isAboveAvail && isRightAvail); isBelowLeftAvail = (isBelowAvail && isLeftAvail); isBelowRightAvail= (isBelowAvail && isRightAvail); Bool isLoopFiltAcrossTilePPS = getCtu(ctuRsAddr)->getSlice()->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); { TComDataCU* ctuCurr = getCtu(ctuRsAddr); TComDataCU* ctuLeft = isLeftAvail ?getCtu(ctuRsAddr-1):NULL; TComDataCU* ctuRight = isRightAvail?getCtu(ctuRsAddr+1):NULL; TComDataCU* ctuAbove = isAboveAvail?getCtu(ctuRsAddr-m_frameWidthInCtus):NULL; TComDataCU* ctuBelow = isBelowAvail?getCtu(ctuRsAddr+m_frameWidthInCtus):NULL; TComDataCU* ctuAboveLeft = isAboveLeftAvail ? getCtu(ctuRsAddr-m_frameWidthInCtus-1):NULL; TComDataCU* ctuAboveRight = isAboveRightAvail? getCtu(ctuRsAddr-m_frameWidthInCtus+1):NULL; TComDataCU* ctuBelowLeft = isBelowLeftAvail ? getCtu(ctuRsAddr+m_frameWidthInCtus-1):NULL; TComDataCU* ctuBelowRight = isBelowRightAvail? getCtu(ctuRsAddr+m_frameWidthInCtus+1):NULL; { //left if(ctuLeft != NULL) { isLeftAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuLeft->getSlice()->getSliceCurStartCtuTsAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true; } //above if(ctuAbove != NULL) { isAboveAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuAbove->getSlice()->getSliceCurStartCtuTsAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true; } //right if(ctuRight != NULL) { isRightAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuRight->getSlice()->getSliceCurStartCtuTsAddr())?ctuRight->getSlice()->getLFCrossSliceBoundaryFlag():true; } //below if(ctuBelow != NULL) { isBelowAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuBelow->getSlice()->getSliceCurStartCtuTsAddr())?ctuBelow->getSlice()->getLFCrossSliceBoundaryFlag():true; } //above-left if(ctuAboveLeft != NULL) { isAboveLeftAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuAboveLeft->getSlice()->getSliceCurStartCtuTsAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true; } //below-right if(ctuBelowRight != NULL) { isBelowRightAvail = (ctuCurr->getSlice()->getSliceCurStartCtuTsAddr() != ctuBelowRight->getSlice()->getSliceCurStartCtuTsAddr())?ctuBelowRight->getSlice()->getLFCrossSliceBoundaryFlag():true; } //above-right if(ctuAboveRight != NULL) { Int curSliceStartTsAddr = ctuCurr->getSlice()->getSliceCurStartCtuTsAddr(); Int aboveRightSliceStartTsAddr = ctuAboveRight->getSlice()->getSliceCurStartCtuTsAddr(); isAboveRightAvail = (curSliceStartTsAddr == aboveRightSliceStartTsAddr)?(true): ( (curSliceStartTsAddr > aboveRightSliceStartTsAddr)?(ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag()) :(ctuAboveRight->getSlice()->getLFCrossSliceBoundaryFlag()) ); } //below-left if(ctuBelowLeft != NULL) { Int curSliceStartTsAddr = ctuCurr->getSlice()->getSliceCurStartCtuTsAddr(); Int belowLeftSliceStartTsAddr = ctuBelowLeft->getSlice()->getSliceCurStartCtuTsAddr(); isBelowLeftAvail = (curSliceStartTsAddr == belowLeftSliceStartTsAddr)?(true): ( (curSliceStartTsAddr > belowLeftSliceStartTsAddr)?(ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag()) :(ctuBelowLeft->getSlice()->getLFCrossSliceBoundaryFlag()) ); } } if(!isLoopFiltAcrossTilePPS) { isLeftAvail = (!isLeftAvail ) ?false:(getTileIdxMap( ctuLeft->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isAboveAvail = (!isAboveAvail ) ?false:(getTileIdxMap( ctuAbove->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isRightAvail = (!isRightAvail ) ?false:(getTileIdxMap( ctuRight->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isBelowAvail = (!isBelowAvail ) ?false:(getTileIdxMap( ctuBelow->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isAboveLeftAvail = (!isAboveLeftAvail ) ?false:(getTileIdxMap( ctuAboveLeft->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isAboveRightAvail= (!isAboveRightAvail) ?false:(getTileIdxMap( ctuAboveRight->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isBelowLeftAvail = (!isBelowLeftAvail ) ?false:(getTileIdxMap( ctuBelowLeft->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); isBelowRightAvail= (!isBelowRightAvail) ?false:(getTileIdxMap( ctuBelowRight->getCtuRsAddr() ) == getTileIdxMap( ctuRsAddr )); } } } TComTile::TComTile() : m_tileWidthInCtus (0) , m_tileHeightInCtus (0) , m_rightEdgePosInCtus (0) , m_bottomEdgePosInCtus (0) , m_firstCtuRsAddr (0) { } TComTile::~TComTile() { } #if MCTS_ENC_CHECK Void getTilePosition(const TComDataCU* const pcCU, UInt &tileXPosInCtus, UInt &tileYPosInCtus, UInt &tileWidthtInCtus, UInt &tileHeightInCtus) { const UInt currentTileIdx = pcCU->getPic()->getPicSym()->getTileIdxMap(pcCU->getCtuRsAddr()); const TComTile *pCurrentTile = pcCU->getPic()->getPicSym()->getTComTile(currentTileIdx); const UInt frameWidthInCtus = pcCU->getPic()->getPicSym()->getFrameWidthInCtus(); const UInt firstCtuRsAddrOfTile = pcCU->getPic()->getPicSym()->getTComTile(pcCU->getPic()->getPicSym()->getTileIdxMap(pcCU->getCtuRsAddr()))->getFirstCtuRsAddr(); tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus; tileYPosInCtus = firstCtuRsAddrOfTile / frameWidthInCtus; tileWidthtInCtus = pCurrentTile->getTileWidthInCtus(); tileHeightInCtus = pCurrentTile->getTileHeightInCtus(); } #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPicSym.h000066400000000000000000000261051442026013100204160ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPicSym.h \brief picture symbol class (header) */ #ifndef __TCOMPICSYM__ #define __TCOMPICSYM__ // Include files #include #include "CommonDef.h" #include "TComSlice.h" #include "TComDataCU.h" class TComSampleAdaptiveOffset; class TComPPS; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class TComTile { private: UInt m_tileWidthInCtus; UInt m_tileHeightInCtus; UInt m_rightEdgePosInCtus; UInt m_bottomEdgePosInCtus; UInt m_firstCtuRsAddr; public: TComTile(); virtual ~TComTile(); Void setTileWidthInCtus ( UInt i ) { m_tileWidthInCtus = i; } UInt getTileWidthInCtus () const { return m_tileWidthInCtus; } Void setTileHeightInCtus ( UInt i ) { m_tileHeightInCtus = i; } UInt getTileHeightInCtus () const { return m_tileHeightInCtus; } Void setRightEdgePosInCtus ( UInt i ) { m_rightEdgePosInCtus = i; } UInt getRightEdgePosInCtus () const { return m_rightEdgePosInCtus; } Void setBottomEdgePosInCtus ( UInt i ) { m_bottomEdgePosInCtus = i; } UInt getBottomEdgePosInCtus () const { return m_bottomEdgePosInCtus; } Void setFirstCtuRsAddr ( UInt i ) { m_firstCtuRsAddr = i; } UInt getFirstCtuRsAddr () const { return m_firstCtuRsAddr; } }; /// picture symbol class class TComPicSym { private: UInt m_frameWidthInCtus; UInt m_frameHeightInCtus; UInt m_uiMinCUWidth; UInt m_uiMinCUHeight; UChar m_uhTotalDepth; ///< max. depth UInt m_numPartitionsInCtu; UInt m_numPartInCtuWidth; UInt m_numPartInCtuHeight; UInt m_numCtusInFrame; std::deque m_apSlices; TComDataCU** m_pictureCtuArray; ///< array of CU data. Int m_numTileColumnsMinus1; Int m_numTileRowsMinus1; std::vector m_tileParameters; UInt* m_ctuTsToRsAddrMap; ///< for a given TS (Tile-Scan; coding order) address, returns the RS (Raster-Scan) address. cf CtbAddrTsToRs in specification. UInt* m_puiTileIdxMap; ///< the map of the tile index relative to CTU raster scan address UInt* m_ctuRsToTsAddrMap; ///< for a given RS (Raster-Scan) address, returns the TS (Tile-Scan; coding order) address. cf CtbAddrRsToTs in specification. #if REDUCED_ENCODER_MEMORY public: #if MCTS_EXTRACTION friend class MctsExtractorTComPicSym; #endif struct DPBPerCtuData { Bool isInter(const UInt absPartAddr) const { return m_pePredMode[absPartAddr] == MODE_INTER; } PartSize getPartitionSize( const UInt absPartAddr ) const { return static_cast( m_pePartSize[absPartAddr] ); } const TComCUMvField* getCUMvField ( RefPicList e ) const { return &m_CUMvField[e]; } const TComSlice* getSlice() const { return m_pSlice; } SChar * m_pePredMode; SChar * m_pePartSize; TComCUMvField m_CUMvField[NUM_REF_PIC_LIST_01]; TComSlice * m_pSlice; }; private: DPBPerCtuData *m_dpbPerCtuData; #endif SAOBlkParam *m_saoBlkParams; #if ADAPTIVE_QP_SELECTION TCoeff* m_pParentARLBuffer; #endif TComSPS m_sps; TComPPS m_pps; Void xInitTiles( ); Void xInitCtuTsRsAddrMaps(); Void setNumTileColumnsMinus1( Int i ) { m_numTileColumnsMinus1 = i; } Void setNumTileRowsMinus1( Int i ) { m_numTileRowsMinus1 = i; } Void setCtuTsToRsAddrMap( Int ctuTsAddr, Int ctuRsAddr ) { *(m_ctuTsToRsAddrMap + ctuTsAddr) = ctuRsAddr; } Void setCtuRsToTsAddrMap( Int ctuRsAddr, Int ctuTsOrder ) { *(m_ctuRsToTsAddrMap + ctuRsAddr) = ctuTsOrder; } public: #if REDUCED_ENCODER_MEMORY Void create ( const TComSPS &sps, const TComPPS &pps, UInt uiMaxDepth, const Bool bAllocateCtuArray ); Void prepareForReconstruction(); Void releaseReconstructionIntermediateData(); Void releaseAllReconstructionData(); #else Void create ( const TComSPS &sps, const TComPPS &pps, UInt uiMaxDepth ); #endif Void destroy (); TComPicSym (); ~TComPicSym(); TComSlice* getSlice(UInt i) { return m_apSlices[i]; } const TComSlice* getSlice(UInt i) const { return m_apSlices[i]; } UInt getFrameWidthInCtus() const { return m_frameWidthInCtus; } UInt getFrameHeightInCtus() const { return m_frameHeightInCtus; } UInt getMinCUWidth() const { return m_uiMinCUWidth; } UInt getMinCUHeight() const { return m_uiMinCUHeight; } UInt getNumberOfCtusInFrame() const { return m_numCtusInFrame; } TComDataCU* getCtu( UInt ctuRsAddr ) { return m_pictureCtuArray[ctuRsAddr]; } const TComDataCU* getCtu( UInt ctuRsAddr ) const { return m_pictureCtuArray[ctuRsAddr]; } const TComSPS& getSPS() const { return m_sps; } const TComPPS& getPPS() const { return m_pps; } #if REDUCED_ENCODER_MEMORY Bool hasDPBPerCtuData() const { return (m_dpbPerCtuData!=0); }; DPBPerCtuData& getDPBPerCtuData(UInt ctuRsAddr) { return m_dpbPerCtuData[ctuRsAddr]; } const DPBPerCtuData& getDPBPerCtuData(UInt ctuRsAddr) const { return m_dpbPerCtuData[ctuRsAddr]; } #endif TComSlice * swapSliceObject(TComSlice* p, UInt i) { p->setSPS(&m_sps); p->setPPS(&m_pps); TComSlice *pTmp=m_apSlices[i];m_apSlices[i] = p; pTmp->setSPS(0); pTmp->setPPS(0); return pTmp; } UInt getNumAllocatedSlice() const { return UInt(m_apSlices.size()); } Void allocateNewSlice(); Void clearSliceBuffer(); UInt getNumPartitionsInCtu() const { return m_numPartitionsInCtu; } UInt getNumPartInCtuWidth() const { return m_numPartInCtuWidth; } UInt getNumPartInCtuHeight() const { return m_numPartInCtuHeight; } Int getNumTileColumnsMinus1() const { return m_numTileColumnsMinus1; } Int getNumTileRowsMinus1() const { return m_numTileRowsMinus1; } Int getNumTiles() const { return (m_numTileRowsMinus1+1)*(m_numTileColumnsMinus1+1); } TComTile* getTComTile ( UInt tileIdx ) { return &(m_tileParameters[tileIdx]); } const TComTile* getTComTile ( UInt tileIdx ) const { return &(m_tileParameters[tileIdx]); } UInt getCtuTsToRsAddrMap( Int ctuTsAddr ) const { return *(m_ctuTsToRsAddrMap + (ctuTsAddr>=m_numCtusInFrame ? m_numCtusInFrame : ctuTsAddr)); } UInt getTileIdxMap( Int ctuRsAddr ) const { return *(m_puiTileIdxMap + ctuRsAddr); } UInt getCtuRsToTsAddrMap( Int ctuRsAddr ) const { return *(m_ctuRsToTsAddrMap + (ctuRsAddr>=m_numCtusInFrame ? m_numCtusInFrame : ctuRsAddr)); } SAOBlkParam* getSAOBlkParam() { return m_saoBlkParams;} const SAOBlkParam* getSAOBlkParam() const { return m_saoBlkParams;} Void deriveLoopFilterBoundaryAvailibility(Int ctuRsAddr, Bool& isLeftAvail, Bool& isRightAvail, Bool& isAboveAvail, Bool& isBelowAvail, Bool& isAboveLeftAvail, Bool& isAboveRightAvail, Bool& isBelowLeftAvail, Bool& isBelowRightAvail); protected: UInt xCalculateNextCtuRSAddr( UInt uiCurrCtuRSAddr ); };// END CLASS DEFINITION TComPicSym #if MCTS_EXTRACTION // Mcts Extractor helper class class MctsExtractorTComPicSym { public: Void setNumberOfCtusInFrame(TComPicSym *picsym, UInt numOfCtusInFrame) { picsym->m_numCtusInFrame = numOfCtusInFrame; } ///< allows setting numOfCtusInFrame which controls memory allocations of several variables in TComPic, TComPicSym, TComLoopFilter and others. Make sure to have equal values of numOfCtusInFrame at time of creation and destruction of an object lifetime to avoid memory leaks. }; #endif //! \} #if MCTS_ENC_CHECK Void getTilePosition(const TComDataCU* const pcCU, UInt &tileXPosInCtus, UInt &tileYPosInCtus, UInt &tileWidthtInCtus, UInt &tileHeightInCtus); #endif #endif // __TCOMPICSYM__ HM-HM-18.0/source/Lib/TLibCommon/TComPicYuv.cpp000066400000000000000000000406061442026013100207660ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPicYuv.cpp \brief picture YUV buffer class */ #include #include #include #ifdef __APPLE__ #include #else #include #endif #include "TComPicYuv.h" #include "Utilities/TVideoIOYuv.h" //! \ingroup TLibCommon //! \{ TComPicYuv::TComPicYuv() { for(UInt i=0; i> componentScaleX; UInt scaledHeight = picHeight >> componentScaleY; unsigned xmargin = m_marginX >> (bScaleMarginChroma ? componentScaleX : 0); unsigned ymargin = m_marginY >> (bScaleMarginChroma ? componentScaleY : 0); Int stride = scaledWidth + 2 * xmargin; Int totalHeight = scaledHeight + 2 * ymargin; m_apiPicBuf[comp] = (Pel*)xMalloc(Pel, stride * totalHeight); m_piPicOrg[comp] = m_apiPicBuf[comp] + ymargin * stride + xmargin; } // initialize pointers for unused components to NULL for (UInt comp = getNumberValidComponents(); comp> getComponentScaleY(ch)) * getStride(ch) + (m_marginX >> getComponentScaleX(ch)); } // initialize pointers for unused components to NULL for(UInt comp=getNumberValidComponents();comp>getChannelTypeScaleY(ch); const Int ctuWidth = maxCUWidth>>getChannelTypeScaleX(ch); const Int stride = getStride(ch); m_ctuOffsetInBuffer[chan] = new Int[numCuInWidth * numCuInHeight]; for (Int cuRow = 0; cuRow < numCuInHeight; cuRow++) { for (Int cuCol = 0; cuCol < numCuInWidth; cuCol++) { m_ctuOffsetInBuffer[chan][cuRow * numCuInWidth + cuCol] = stride * cuRow * ctuHeight + cuCol * ctuWidth; } } m_subCuOffsetInBuffer[chan] = new Int[(size_t)1 << (2 * maxCUDepth)]; const Int numSubBlockPartitions=(1<> maxCUDepth); const Int minSubBlockWidth =(ctuWidth >> maxCUDepth); for (Int buRow = 0; buRow < numSubBlockPartitions; buRow++) { for (Int buCol = 0; buCol < numSubBlockPartitions; buCol++) { m_subCuOffsetInBuffer[chan][(buRow << maxCUDepth) + buCol] = stride * buRow * minSubBlockHeight + buCol * minSubBlockWidth; } } } } Void TComPicYuv::destroy() { for(Int comp=0; compgetChromaFormat() ); for(Int comp=0; compgetWidth(compId) == width); assert(pcPicYuvDst->getHeight(compId) == height); if (strideSrc==pcPicYuvDst->getStride(compId)) { ::memcpy ( pcPicYuvDst->getBuf(compId), getBuf(compId), sizeof(Pel)*strideSrc*getTotalHeight(compId)); } else { const Pel *pSrc = getAddr(compId); Pel *pDest = pcPicYuvDst->getAddr(compId); const UInt strideDest = pcPicYuvDst->getStride(compId); for(Int y=0; ygetChromaFormat()); for (Int comp = 0; comp < getNumberValidComponents(); comp++) { const ComponentID compId = ComponentID(comp); const Int width = getWidth(compId); const Int height = getHeight(compId); const Int strideSrc = getStride(compId, bScaleMarginChromaSrc); assert(pcPicYuvDst->getWidth(compId) == width); assert(pcPicYuvDst->getHeight(compId) == height); if (strideSrc == pcPicYuvDst->getStride(compId, bScaleMarginChromaDst)) { ::memcpy(pcPicYuvDst->getBuf(compId), getBuf(compId), sizeof(Pel) * strideSrc * getTotalHeight(compId, bScaleMarginChromaSrc)); } else { const Pel* pSrc = getAddr(compId); Pel* pDest = pcPicYuvDst->getAddr(compId); const UInt strideDest = pcPicYuvDst->getStride(compId, bScaleMarginChromaDst); for (Int y = 0; y < height; y++, pSrc += strideSrc, pDest += strideDest) { ::memcpy(pDest, pSrc, width * sizeof(Pel)); } } } } Void TComPicYuv::copyTo(TComPicYuv* pcPicYuvDst, ComponentID compIdSrc, ComponentID compIdDst, const Bool bScaleMarginChromaSrc, const Bool bScaleMarginChromaDst) const { const Int width = getWidth(compIdSrc); // source const Int height = getHeight(compIdSrc); const Int strideSrc = getStride(compIdSrc, bScaleMarginChromaSrc); assert(pcPicYuvDst->getWidth(compIdDst) == width); assert(pcPicYuvDst->getHeight(compIdDst) == height); if (strideSrc == pcPicYuvDst->getStride(compIdDst, bScaleMarginChromaDst)) { ::memcpy(pcPicYuvDst->getBuf(compIdDst), getBuf(compIdSrc), sizeof(Pel) * strideSrc * getTotalHeight(compIdSrc,false)); } else { const Pel* pSrc = getAddr(compIdSrc); Pel* pDest = pcPicYuvDst->getAddr(compIdDst); const UInt strideDest = pcPicYuvDst->getStride(compIdDst, bScaleMarginChromaDst); for (Int y = 0; y < height; y++, pSrc += strideSrc, pDest += strideDest) { ::memcpy(pDest, pSrc, width * sizeof(Pel)); } } } #endif Void TComPicYuv::extendPicBorder () { if ( m_bIsBorderExtended ) { return; } for(Int comp=0; comp8) { is16bit=true; } } for(Int comp = 0; comp < getNumberValidComponents(); comp++) { const ComponentID compId = ComponentID(comp); const Pel *pi = getAddr(compId); #if JVET_X0048_X0103_FILM_GRAIN const Int stride = getStride(compId, bScaleMarginChroma); #else const Int stride = getStride(compId); #endif const Int height = getHeight(compId); const Int width = getWidth(compId); if (is16bit) { for (Int y = 0; y < height; y++ ) { for (Int x = 0; x < width; x++ ) { UChar uc = (UChar)((pi[x]>>0) & 0xff); fwrite( &uc, sizeof(UChar), 1, pFile ); uc = (UChar)((pi[x]>>8) & 0xff); fwrite( &uc, sizeof(UChar), 1, pFile ); } pi += stride; } } else { const Int shift = bitDepths.recon[toChannelType(compId)] - 8; const Int offset = (shift>0)?(1<<(shift-1)):0; for (Int y = 0; y < height; y++ ) { for (Int x = 0; x < width; x++ ) { UChar uc = (UChar)Clip3(0, 255, (pi[x]+offset)>>shift); fwrite( &uc, sizeof(UChar), 1, pFile ); } pi += stride; } } } fclose(pFile); } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPicYuv.h000066400000000000000000000305731442026013100204350ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPicYuv.h \brief picture YUV buffer class (header) */ #ifndef __TCOMPICYUV__ #define __TCOMPICYUV__ #include #include "CommonDef.h" #include "TComRom.h" #include "TComChromaFormat.h" #include "SEI.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// picture YUV buffer class class TComPicYuv { private: // ------------------------------------------------------------------------------------------------ // YUV buffer // ------------------------------------------------------------------------------------------------ Pel* m_apiPicBuf[MAX_NUM_COMPONENT]; ///< Buffer (including margin) Pel* m_piPicOrg[MAX_NUM_COMPONENT]; ///< m_apiPicBufY + m_iMarginLuma*getStride() + m_iMarginLuma // ------------------------------------------------------------------------------------------------ // Parameter for general YUV buffer usage // ------------------------------------------------------------------------------------------------ Int m_picWidth; ///< Width of picture in pixels Int m_picHeight; ///< Height of picture in pixels ChromaFormat m_chromaFormatIDC; ///< Chroma Format Int* m_ctuOffsetInBuffer[MAX_NUM_CHANNEL_TYPE]; ///< Gives an offset in the buffer for a given CTU (and channel) Int* m_subCuOffsetInBuffer[MAX_NUM_CHANNEL_TYPE];///< Gives an offset in the buffer for a given sub-CU (and channel), relative to start of CTU Int m_marginX; ///< margin of Luma channel (chroma's may be smaller, depending on ratio) Int m_marginY; ///< margin of Luma channel (chroma's may be smaller, depending on ratio) Bool m_bIsBorderExtended; public: TComPicYuv (); virtual ~TComPicYuv (); // ------------------------------------------------------------------------------------------------ // Memory management // ------------------------------------------------------------------------------------------------ Void create (const Int picWidth, const Int picHeight, const ChromaFormat chromaFormatIDC, const UInt maxCUWidth, ///< used for generating offsets to CUs. const UInt maxCUHeight, ///< used for generating offsets to CUs. const UInt maxCUDepth, ///< used for generating offsets to CUs. const Bool bUseMargin); ///< if true, then a margin of uiMaxCUWidth+16 and uiMaxCUHeight+16 is created around the image. Void createWithoutCUInfo(const Int picWidth, const Int picHeight, const ChromaFormat chromaFormatIDC, const Bool bUseMargin=false, ///< if true, then a margin of uiMaxCUWidth+16 and uiMaxCUHeight+16 is created around the image. const UInt maxCUWidth=0, ///< used for margin only const UInt maxCUHeight=0); ///< used for margin only #if JVET_X0048_X0103_FILM_GRAIN Void createWithPadding (const Int picWidth, const Int picHeight, const ChromaFormat chromaFormatIDC, const Bool bUseMargin=false, ///< if true, then a margin of padWidth and padHeight is created around the image. const Bool bScaleMarginChroma=true, ///< if true, margin is scaled based on chroma format. Otherwise, the same padding is used for all components. const UInt padWidth=0, ///< used for margin only const UInt padHeight=0); ///< used for margin only #endif Void destroy (); // The following have been removed - Use CHROMA_400 in the above function call. //Void createLuma ( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uhMaxCUDepth ); //Void destroyLuma (); // ------------------------------------------------------------------------------------------------ // Get information of picture // ------------------------------------------------------------------------------------------------ Int getWidth (const ComponentID id) const { return m_picWidth >> getComponentScaleX(id); } Int getHeight (const ComponentID id) const { return m_picHeight >> getComponentScaleY(id); } ChromaFormat getChromaFormat () const { return m_chromaFormatIDC; } UInt getNumberValidComponents() const { return ::getNumberValidComponents(m_chromaFormatIDC); } Int getStride (const ComponentID id) const { return ((m_picWidth ) + (m_marginX <<1)) >> getComponentScaleX(id); } private: Int getStride (const ChannelType id) const { return ((m_picWidth ) + (m_marginX <<1)) >> getChannelTypeScaleX(id); } public: Int getTotalHeight (const ComponentID id) const { return ((m_picHeight ) + (m_marginY <<1)) >> getComponentScaleY(id); } #if JVET_X0048_X0103_FILM_GRAIN Int getStride(const ComponentID id, const Bool bScaleMarginChroma) const { unsigned xmargin = m_marginX >> (bScaleMarginChroma ? getComponentScaleX(id) : 0); return ((m_picWidth >> getComponentScaleX(id)) + (2 * xmargin)); } Int getTotalHeight(const ComponentID id, const Bool bScaleMarginChroma) const { unsigned ymargin = m_marginY >> (bScaleMarginChroma ? getComponentScaleY(id) : 0); return ((m_picHeight >> getComponentScaleY(id)) + (2 * ymargin)); } Pel& at(const int& x, const int& y, const ComponentID id, const Bool bScaleMarginChroma = true) { int stride = getStride(id, bScaleMarginChroma); return m_piPicOrg[id][y * stride + x]; } const Pel& at(const int& x, const int& y, const ComponentID id, const Bool bScaleMarginChroma = true) const { int stride = getStride(id, bScaleMarginChroma); return m_piPicOrg[id][y * stride + x]; } #endif Int getMarginX (const ComponentID id) const { return m_marginX >> getComponentScaleX(id); } Int getMarginY (const ComponentID id) const { return m_marginY >> getComponentScaleY(id); } // ------------------------------------------------------------------------------------------------ // Access function for picture buffer // ------------------------------------------------------------------------------------------------ // Access starting position of picture buffer with margin Pel* getBuf (const ComponentID ch) { return m_apiPicBuf[ch]; } const Pel* getBuf (const ComponentID ch) const { return m_apiPicBuf[ch]; } // Access starting position of original picture Pel* getAddr (const ComponentID ch) { return m_piPicOrg[ch]; } const Pel* getAddr (const ComponentID ch) const { return m_piPicOrg[ch]; } // Access starting position of original picture for specific coding unit (CU) or partition unit (PU) Pel* getAddr (const ComponentID ch, const Int ctuRSAddr ) { return m_piPicOrg[ch] + m_ctuOffsetInBuffer[ch==0?0:1][ ctuRSAddr ]; } const Pel* getAddr (const ComponentID ch, const Int ctuRSAddr ) const { return m_piPicOrg[ch] + m_ctuOffsetInBuffer[ch==0?0:1][ ctuRSAddr ]; } Pel* getAddr (const ComponentID ch, const Int ctuRSAddr, const Int uiAbsZorderIdx ) { return m_piPicOrg[ch] + m_ctuOffsetInBuffer[ch==0?0:1][ctuRSAddr] + m_subCuOffsetInBuffer[ch==0?0:1][g_auiZscanToRaster[uiAbsZorderIdx]]; } const Pel* getAddr (const ComponentID ch, const Int ctuRSAddr, const Int uiAbsZorderIdx ) const { return m_piPicOrg[ch] + m_ctuOffsetInBuffer[ch==0?0:1][ctuRSAddr] + m_subCuOffsetInBuffer[ch==0?0:1][g_auiZscanToRaster[uiAbsZorderIdx]]; } UInt getComponentScaleX(const ComponentID id) const { return ::getComponentScaleX(id, m_chromaFormatIDC); } UInt getComponentScaleY(const ComponentID id) const { return ::getComponentScaleY(id, m_chromaFormatIDC); } UInt getChannelTypeScaleX(const ChannelType id) const { return ::getChannelTypeScaleX(id, m_chromaFormatIDC); } UInt getChannelTypeScaleY(const ChannelType id) const { return ::getChannelTypeScaleY(id, m_chromaFormatIDC); } // ------------------------------------------------------------------------------------------------ // Miscellaneous // ------------------------------------------------------------------------------------------------ // Copy function to picture #if JVET_X0048_X0103_FILM_GRAIN Void copyTo(TComPicYuv* pcPicYuvDst, ComponentID compIdSrc, ComponentID compIdDst, const Bool bScaleMarginChromaSrc, const Bool bScaleMarginChromaDst) const; Void extendPicBorder(const ComponentID compId, const Int marginX, const Int marginY, const Bool bScaleMarginChroma = true); Void copyToPic(TComPicYuv* pcPicYuvDst, const Bool bScaleMarginChromaSrc, const Bool bScaleMarginChromaDst) const; #endif Void copyToPic(TComPicYuv* pcPicYuvDst) const; // Extend function of picture buffer Void extendPicBorder (); // Dump picture #if JVET_X0048_X0103_FILM_GRAIN Void dump(const std::string& fileName, const BitDepths& bitDepths, const Bool bAppend = false, const Bool bForceTo8Bit = false, const Bool bScaleMarginChroma = true) const; #else Void dump(const std::string& fileName, const BitDepths& bitDepths, const Bool bAppend = false, const Bool bForceTo8Bit = false) const; #endif // Set border extension flag Void setBorderExtension(Bool b) { m_bIsBorderExtended = b; } };// END CLASS DEFINITION TComPicYuv // These functions now return the length of the digest strings. UInt calcChecksum(const TComPicYuv& pic, TComPictureHash &digest, const BitDepths &bitDepths); UInt calcCRC (const TComPicYuv& pic, TComPictureHash &digest, const BitDepths &bitDepths); UInt calcMD5 (const TComPicYuv& pic, TComPictureHash &digest, const BitDepths &bitDepths); std::string hashToString(const TComPictureHash &digest, Int numChar); //! \} #endif // __TCOMPICYUV__ HM-HM-18.0/source/Lib/TLibCommon/TComPicYuvMD5.cpp000066400000000000000000000172041442026013100212720ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "TComPicYuv.h" #include "libmd5/MD5.h" //! \ingroup TLibCommon //! \{ /** * Update md5 using n samples from plane, each sample is adjusted to * OUTBIT_BITDEPTH_DIV8. */ template static Void md5_block(MD5& md5, const Pel* plane, UInt n) { /* create a 64 byte buffer for packing Pel's into */ UChar buf[64/OUTPUT_BITDEPTH_DIV8][OUTPUT_BITDEPTH_DIV8]; for (UInt i = 0; i < n; i++) { Pel pel = plane[i]; /* perform bitdepth and endian conversion */ for (UInt d = 0; d < OUTPUT_BITDEPTH_DIV8; d++) { buf[i][d] = pel >> (d*8); } } md5.update((UChar*)buf, n * OUTPUT_BITDEPTH_DIV8); } /** * Update md5 with all samples in plane in raster order, each sample * is adjusted to OUTBIT_BITDEPTH_DIV8. */ template static Void md5_plane(MD5& md5, const Pel* plane, UInt width, UInt height, UInt stride) { /* N is the number of samples to process per md5 update. * All N samples must fit in buf */ UInt N = 32; UInt width_modN = width % N; UInt width_less_modN = width - width_modN; for (UInt y = 0; y < height; y++) { /* convert pels into unsigned chars in little endian byte order. * NB, for 8bit data, data is truncated to 8bits. */ for (UInt x = 0; x < width_less_modN; x += N) { md5_block(md5, &plane[y*stride + x], N); } /* mop up any of the remaining line */ md5_block(md5, &plane[y*stride + width_less_modN], width_modN); } } UInt compCRC(Int bitdepth, const Pel* plane, UInt width, UInt height, UInt stride, TComPictureHash &digest) { UInt crcMsb; UInt bitVal; UInt crcVal = 0xffff; UInt bitIdx; for (UInt y = 0; y < height; y++) { for (UInt x = 0; x < width; x++) { // take CRC of first pictureData byte for(bitIdx=0; bitIdx<8; bitIdx++) { crcMsb = (crcVal >> 15) & 1; bitVal = (plane[y*stride+x] >> (7 - bitIdx)) & 1; crcVal = (((crcVal << 1) + bitVal) & 0xffff) ^ (crcMsb * 0x1021); } // take CRC of second pictureData byte if bit depth is greater than 8-bits if(bitdepth > 8) { for(bitIdx=0; bitIdx<8; bitIdx++) { crcMsb = (crcVal >> 15) & 1; bitVal = (plane[y*stride+x] >> (15 - bitIdx)) & 1; crcVal = (((crcVal << 1) + bitVal) & 0xffff) ^ (crcMsb * 0x1021); } } } } for(bitIdx=0; bitIdx<16; bitIdx++) { crcMsb = (crcVal >> 15) & 1; crcVal = ((crcVal << 1) & 0xffff) ^ (crcMsb * 0x1021); } digest.hash.push_back((crcVal>>8) & 0xff); digest.hash.push_back( crcVal & 0xff); return 2; } UInt calcCRC(const TComPicYuv& pic, TComPictureHash &digest, const BitDepths &bitDepths) { UInt digestLen=0; digest.hash.clear(); for(Int chan=0; chan> 8) ^ (y >> 8); checksum = (checksum + ((plane[y*stride+x] & 0xff) ^ xor_mask)) & 0xffffffff; if(bitdepth > 8) { checksum = (checksum + ((plane[y*stride+x]>>8) ^ xor_mask)) & 0xffffffff; } } } digest.hash.push_back((checksum>>24) & 0xff); digest.hash.push_back((checksum>>16) & 0xff); digest.hash.push_back((checksum>>8) & 0xff); digest.hash.push_back( checksum & 0xff); return 4; } UInt calcChecksum(const TComPicYuv& pic, TComPictureHash &digest, const BitDepths &bitDepths) { UInt digestLen=0; digest.hash.clear(); for(Int chan=0; chan : (MD5PlaneFunc)md5_plane<2>; UChar tmp_digest[MD5_DIGEST_STRING_LENGTH]; md5_plane_func(md5[compID], pic.getAddr(compID), pic.getWidth(compID), pic.getHeight(compID), pic.getStride(compID)); md5[compID].finalize(tmp_digest); for(UInt i=0; i> 4]; result += hex[digest.hash[pos] & 0xf]; } return result; } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPrediction.cpp000066400000000000000000001121311442026013100216400ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPrediction.cpp \brief prediction class */ #include #include "TComPrediction.h" #include "TComPic.h" #include "TComTU.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Tables // ==================================================================================================================== const UChar TComPrediction::m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS] = { { // Luma 10, //4x4 7, //8x8 1, //16x16 0, //32x32 10, //64x64 }, { // Chroma 10, //4xn 7, //8xn 1, //16xn 0, //32xn 10, //64xn } }; // ==================================================================================================================== // Constructor / destructor / initialize // ==================================================================================================================== TComPrediction::TComPrediction() : m_pLumaRecBuffer(0) , m_iLumaRecStride(0) { for(UInt ch=0; ch>1) + 1) { m_iLumaRecStride = (MAX_CU_SIZE>>1) + 1; if (!m_pLumaRecBuffer) { m_pLumaRecBuffer = new Pel[ m_iLumaRecStride * m_iLumaRecStride ]; } } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== // Function for calculating DC value of the reference samples used in Intra prediction //NOTE: Bit-Limit - 25-bit source Pel TComPrediction::predIntraGetPredValDC( const Pel* pSrc, Int iSrcStride, UInt iWidth, UInt iHeight) { assert(iWidth > 0 && iHeight > 0); Int iInd, iSum = 0; Pel pDcVal; for (iInd = 0;iInd < iWidth;iInd++) { iSum += pSrc[iInd-iSrcStride]; } for (iInd = 0;iInd < iHeight;iInd++) { iSum += pSrc[iInd*iSrcStride-1]; } pDcVal = (iSum + iWidth) / (iWidth + iHeight); return pDcVal; } // Function for deriving the angular Intra predictions /** Function for deriving the simplified angular intra predictions. * \param bitDepth bit depth * \param pSrc pointer to reconstructed sample array * \param srcStride the stride of the reconstructed sample array * \param pTrueDst reference to pointer for the prediction sample array * \param dstStrideTrue the stride of the prediction sample array * \param uiWidth the width of the block * \param uiHeight the height of the block * \param channelType type of pel array (luma/chroma) * \param format chroma format * \param dirMode the intra prediction mode index * \param blkAboveAvailable boolean indication if the block above is available * \param blkLeftAvailable boolean indication if the block to the left is available * \param bEnableEdgeFilters indication whether to enable edge filters * * This function derives the prediction samples for the angular mode based on the prediction direction indicated by * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and * the reference row above the block in the case of vertical prediction or displacement of the rightmost column * of the block and reference column left from the block in the case of the horizontal prediction. The displacement * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples, * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken * from the extended main reference. */ //NOTE: Bit-Limit - 25-bit source Void TComPrediction::xPredIntraAng( Int bitDepth, const Pel* pSrc, Int srcStride, Pel* pTrueDst, Int dstStrideTrue, UInt uiWidth, UInt uiHeight, ChannelType channelType, UInt dirMode, const Bool bEnableEdgeFilters ) { Int width=Int(uiWidth); Int height=Int(uiHeight); // Map the mode index to main prediction direction and angle assert( dirMode != PLANAR_IDX ); //no planar const Bool modeDC = dirMode==DC_IDX; // Do the DC prediction if (modeDC) { const Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height); for (Int y=height;y>0;y--, pTrueDst+=dstStrideTrue) { for (Int x=0; x= 18); const Int intraPredAngleMode = (bIsModeVer) ? (Int)dirMode - VER_IDX : -((Int)dirMode - HOR_IDX); const Int absAngMode = abs(intraPredAngleMode); const Int signAng = intraPredAngleMode < 0 ? -1 : 1; const Bool edgeFilter = bEnableEdgeFilters && isLuma(channelType) && (width <= MAXIMUM_INTRA_FILTERED_WIDTH) && (height <= MAXIMUM_INTRA_FILTERED_HEIGHT); // Set bitshifts and scale the angle parameter to block size static const Int angTable[9] = {0, 2, 5, 9, 13, 17, 21, 26, 32}; static const Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle Int invAngle = invAngTable[absAngMode]; Int absAng = angTable[absAngMode]; Int intraPredAngle = signAng * absAng; Pel* refMain; Pel* refSide; Pel refAbove[2*MAX_CU_SIZE+1]; Pel refLeft[2*MAX_CU_SIZE+1]; // Initialize the Main and Left reference array. if (intraPredAngle < 0) { const Int refMainOffsetPreScale = (bIsModeVer ? height : width ) - 1; const Int refMainOffset = height - 1; for (Int x=0;x(refMainOffsetPreScale+1)*intraPredAngle>>5; k--) { invAngleSum += invAngle; refMain[k] = refSide[invAngleSum>>8]; } } else { for (Int x=0;x<2*width+1;x++) { refAbove[x] = pSrc[x-srcStride-1]; } for (Int y=0;y<2*height+1;y++) { refLeft[y] = pSrc[(y-1)*srcStride-1]; } refMain = bIsModeVer ? refAbove : refLeft ; refSide = bIsModeVer ? refLeft : refAbove; } // swap width/height if we are doing a horizontal mode: Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE]; const Int dstStride = bIsModeVer ? dstStrideTrue : MAX_CU_SIZE; Pel *pDst = bIsModeVer ? pTrueDst : tempArray; if (!bIsModeVer) { std::swap(width, height); } if (intraPredAngle == 0) // pure vertical or pure horizontal { for (Int y=0;y> 1) ); } } } else { Pel *pDsty=pDst; for (Int y=0, deltaPos=intraPredAngle; y> 5; const Int deltaFract = deltaPos & (32 - 1); if (deltaFract) { // Do linear filtering const Pel *pRM=refMain+deltaInt+1; Int lastRefMainPel=*pRM++; for (Int x=0;x> 5 ); lastRefMainPel=thisRefMainPel; } } else { // Just copy the integer samples for (Int x=0;x= 0 ); // 4x 4 assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128 //assert( iWidth == iHeight ); Pel *pDst = piPred; // get starting pixel in block const Int sw = (2 * iWidth + 1); if ( bUseLosslessDPCM ) { const Pel *ptrSrc = getPredictorPtr( compID, false ); // Sample Adaptive intra-Prediction (SAP) if (uiDirMode==HOR_IDX) { // left column filled with reference samples // remaining columns filled with piOrg data (if available). for(Int y=0; yisRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx)); #if O0043_BEST_EFFORT_DECODING const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType); #else const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType); #endif xPredIntraAng( channelsBitDepthForPrediction, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, uiDirMode, enableEdgeFilters ); if( uiDirMode == DC_IDX ) { xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType ); } } } } /** Check for identical motion in both motion vector direction of a bi-directional predicted CU * \returns true, if motion vectors and reference pictures match */ Bool TComPrediction::xCheckIdenticalMotion ( TComDataCU* pcCU, UInt PartAddr ) { if( pcCU->getSlice()->isInterB() && !pcCU->getSlice()->getPPS()->getWPBiPred() ) { if( pcCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx(PartAddr) >= 0 && pcCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx(PartAddr) >= 0) { Int RefPOCL0 = pcCU->getSlice()->getRefPic(REF_PIC_LIST_0, pcCU->getCUMvField(REF_PIC_LIST_0)->getRefIdx(PartAddr))->getPOC(); Int RefPOCL1 = pcCU->getSlice()->getRefPic(REF_PIC_LIST_1, pcCU->getCUMvField(REF_PIC_LIST_1)->getRefIdx(PartAddr))->getPOC(); if(RefPOCL0 == RefPOCL1 && pcCU->getCUMvField(REF_PIC_LIST_0)->getMv(PartAddr) == pcCU->getCUMvField(REF_PIC_LIST_1)->getMv(PartAddr)) { return true; } } } return false; } Void TComPrediction::motionCompensation ( TComDataCU* pcCU, TComYuv* pcYuvPred, RefPicList eRefPicList, Int iPartIdx ) { Int iWidth; Int iHeight; UInt uiPartAddr; const TComSlice *pSlice = pcCU->getSlice(); const SliceType sliceType = pSlice->getSliceType(); const TComPPS &pps = *(pSlice->getPPS()); if ( iPartIdx >= 0 ) { pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight ); if ( eRefPicList != REF_PIC_LIST_X ) { if( (sliceType == P_SLICE && pps.getUseWP()) || (sliceType == B_SLICE && pps.getWPBiPred())) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, true ); xWeightedPredictionUni( pcCU, pcYuvPred, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred ); } else { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred ); } } else { if ( xCheckIdenticalMotion( pcCU, uiPartAddr ) ) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred ); } else { xPredInterBi (pcCU, uiPartAddr, iWidth, iHeight, pcYuvPred ); } } return; } for ( iPartIdx = 0; iPartIdx < pcCU->getNumPartitions(); iPartIdx++ ) { pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iWidth, iHeight ); if ( eRefPicList != REF_PIC_LIST_X ) { if( (sliceType == P_SLICE && pps.getUseWP()) || (sliceType == B_SLICE && pps.getWPBiPred())) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred, true ); xWeightedPredictionUni( pcCU, pcYuvPred, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred ); } else { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcYuvPred ); } } else { if ( xCheckIdenticalMotion( pcCU, uiPartAddr ) ) { xPredInterUni (pcCU, uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred ); } else { xPredInterBi (pcCU, uiPartAddr, iWidth, iHeight, pcYuvPred ); } } } return; } Void TComPrediction::xPredInterUni ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, RefPicList eRefPicList, TComYuv* pcYuvPred, Bool bi ) { Int iRefIdx = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr ); assert (iRefIdx >= 0); TComMv cMv = pcCU->getCUMvField( eRefPicList )->getMv( uiPartAddr ); pcCU->clipMv(cMv); for (UInt comp=COMPONENT_Y; compgetNumberValidComponents(); comp++) { const ComponentID compID=ComponentID(comp); xPredInterBlk (compID, pcCU, pcCU->getSlice()->getRefPic( eRefPicList, iRefIdx )->getPicYuvRec(), uiPartAddr, &cMv, iWidth, iHeight, pcYuvPred, bi, pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)) ); } } Void TComPrediction::xPredInterBi ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, TComYuv* pcYuvPred ) { TComYuv* pcMbYuv; Int iRefIdx[NUM_REF_PIC_LIST_01] = {-1, -1}; for ( UInt refList = 0; refList < NUM_REF_PIC_LIST_01; refList++ ) { RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); iRefIdx[refList] = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr ); if ( iRefIdx[refList] < 0 ) { continue; } assert( iRefIdx[refList] < pcCU->getSlice()->getNumRefIdx(eRefPicList) ); pcMbYuv = &m_acYuvPred[refList]; if( pcCU->getCUMvField( REF_PIC_LIST_0 )->getRefIdx( uiPartAddr ) >= 0 && pcCU->getCUMvField( REF_PIC_LIST_1 )->getRefIdx( uiPartAddr ) >= 0 ) { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv, true ); } else { if ( ( pcCU->getSlice()->getPPS()->getUseWP() && pcCU->getSlice()->getSliceType() == P_SLICE ) || ( pcCU->getSlice()->getPPS()->getWPBiPred() && pcCU->getSlice()->getSliceType() == B_SLICE ) ) { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv, true ); } else { xPredInterUni ( pcCU, uiPartAddr, iWidth, iHeight, eRefPicList, pcMbYuv ); } } } if ( pcCU->getSlice()->getPPS()->getWPBiPred() && pcCU->getSlice()->getSliceType() == B_SLICE ) { xWeightedPredictionBi( pcCU, &m_acYuvPred[REF_PIC_LIST_0], &m_acYuvPred[REF_PIC_LIST_1], iRefIdx[REF_PIC_LIST_0], iRefIdx[REF_PIC_LIST_1], uiPartAddr, iWidth, iHeight, pcYuvPred ); } else if ( pcCU->getSlice()->getPPS()->getUseWP() && pcCU->getSlice()->getSliceType() == P_SLICE ) { xWeightedPredictionUni( pcCU, &m_acYuvPred[REF_PIC_LIST_0], uiPartAddr, iWidth, iHeight, REF_PIC_LIST_0, pcYuvPred ); } else { xWeightedAverage( &m_acYuvPred[REF_PIC_LIST_0], &m_acYuvPred[REF_PIC_LIST_1], iRefIdx[REF_PIC_LIST_0], iRefIdx[REF_PIC_LIST_1], uiPartAddr, iWidth, iHeight, pcYuvPred, pcCU->getSlice()->getSPS()->getBitDepths() ); } } /** * \brief Generate motion-compensated block * * \param compID Colour component ID * \param cu Pointer to current CU * \param refPic Pointer to reference picture * \param partAddr Address of block within CU * \param mv Motion vector * \param width Width of block * \param height Height of block * \param dstPic Pointer to destination picture * \param bi Flag indicating whether bipred is used * \param bitDepth Bit depth */ Void TComPrediction::xPredInterBlk(const ComponentID compID, TComDataCU *cu, TComPicYuv *refPic, UInt partAddr, TComMv *mv, Int width, Int height, TComYuv *dstPic, Bool bi, const Int bitDepth ) { Int refStride = refPic->getStride(compID); Int dstStride = dstPic->getStride(compID); Int shiftHor=(2+refPic->getComponentScaleX(compID)); Int shiftVer=(2+refPic->getComponentScaleY(compID)); Int refOffset = (mv->getHor() >> shiftHor) + (mv->getVer() >> shiftVer) * refStride; Pel* ref = refPic->getAddr(compID, cu->getCtuRsAddr(), cu->getZorderIdxInCtu() + partAddr ) + refOffset; Pel* dst = dstPic->getAddr( compID, partAddr ); Int xFrac = mv->getHor() & ((1<getVer() & ((1<> refPic->getComponentScaleX(compID); UInt cxHeight = height >> refPic->getComponentScaleY(compID); const ChromaFormat chFmt = cu->getPic()->getChromaFormat(); if ( yFrac == 0 ) { m_if.filterHor(compID, ref, refStride, dst, dstStride, cxWidth, cxHeight, xFrac, !bi, chFmt, bitDepth); } else if ( xFrac == 0 ) { m_if.filterVer(compID, ref, refStride, dst, dstStride, cxWidth, cxHeight, yFrac, true, !bi, chFmt, bitDepth); } else { Int tmpStride = m_filteredBlockTmp[0].getStride(compID); Pel* tmp = m_filteredBlockTmp[0].getAddr(compID); const Int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA; m_if.filterHor(compID, ref - ((vFilterSize>>1) -1)*refStride, refStride, tmp, tmpStride, cxWidth, cxHeight+vFilterSize-1, xFrac, false, chFmt, bitDepth); m_if.filterVer(compID, tmp + ((vFilterSize>>1) -1)*tmpStride, tmpStride, dst, dstStride, cxWidth, cxHeight, yFrac, false, !bi, chFmt, bitDepth); } } Void TComPrediction::xWeightedAverage( TComYuv* pcYuvSrc0, TComYuv* pcYuvSrc1, Int iRefIdx0, Int iRefIdx1, UInt uiPartIdx, Int iWidth, Int iHeight, TComYuv* pcYuvDst, const BitDepths &clipBitDepths ) { if( iRefIdx0 >= 0 && iRefIdx1 >= 0 ) { pcYuvDst->addAvg( pcYuvSrc0, pcYuvSrc1, uiPartIdx, iWidth, iHeight, clipBitDepths ); } else if ( iRefIdx0 >= 0 && iRefIdx1 < 0 ) { pcYuvSrc0->copyPartToPartYuv( pcYuvDst, uiPartIdx, iWidth, iHeight ); } else if ( iRefIdx0 < 0 && iRefIdx1 >= 0 ) { pcYuvSrc1->copyPartToPartYuv( pcYuvDst, uiPartIdx, iWidth, iHeight ); } } // AMVP Void TComPrediction::getMvPredAMVP( TComDataCU* pcCU, UInt uiPartIdx, UInt uiPartAddr, RefPicList eRefPicList, TComMv& rcMvPred ) { AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); if( pcAMVPInfo->iN <= 1 ) { rcMvPred = pcAMVPInfo->m_acMvCand[0]; pcCU->setMVPIdxSubParts( 0, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); return; } assert(pcCU->getMVPIdx(eRefPicList,uiPartAddr) >= 0); rcMvPred = pcAMVPInfo->m_acMvCand[pcCU->getMVPIdx(eRefPicList,uiPartAddr)]; return; } /** Function for deriving planar intra prediction. * \param pSrc pointer to reconstructed sample array * \param srcStride the stride of the reconstructed sample array * \param rpDst reference to pointer for the prediction sample array * \param dstStride the stride of the prediction sample array * \param width the width of the block * \param height the height of the block * \param channelType type of pel array (luma, chroma) * \param format chroma format * * This function derives the prediction samples for planar mode (intra coding). */ //NOTE: Bit-Limit - 24-bit source Void TComPrediction::xPredIntraPlanar( const Pel* pSrc, Int srcStride, Pel* rpDst, Int dstStride, UInt width, UInt height ) { assert(width <= height); Int leftColumn[MAX_CU_SIZE+1] = {0}; Int topRow[MAX_CU_SIZE+1] = {0}; Int bottomRow[MAX_CU_SIZE] = {0}; Int rightColumn[MAX_CU_SIZE] = {0}; UInt shift1Dhor = g_aucConvertToBit[ width ] + 2; UInt shift1Dver = g_aucConvertToBit[ height ] + 2; // Get left and above reference column and row for(Int k=0;k>topRowShift); rpDst[y*dstStride+x] = ( horPred + vertPred ) >> (shift1Dhor+1); } } } /** Function for filtering intra DC predictor. * \param pSrc pointer to reconstructed sample array * \param iSrcStride the stride of the reconstructed sample array * \param pDst reference to pointer for the prediction sample array * \param iDstStride the stride of the prediction sample array * \param iWidth the width of the block * \param iHeight the height of the block * \param channelType type of pel array (luma, chroma) * * This function performs filtering left and top edges of the prediction samples for DC mode (intra coding). */ Void TComPrediction::xDCPredFiltering( const Pel* pSrc, Int iSrcStride, Pel* pDst, Int iDstStride, Int iWidth, Int iHeight, ChannelType channelType ) { Int x, y, iDstStride2, iSrcStride2; if (isLuma(channelType) && (iWidth <= MAXIMUM_INTRA_FILTERED_WIDTH) && (iHeight <= MAXIMUM_INTRA_FILTERED_HEIGHT)) { //top-left pDst[0] = (Pel)((pSrc[-iSrcStride] + pSrc[-1] + 2 * pDst[0] + 2) >> 2); //top row (vertical filter) for ( x = 1; x < iWidth; x++ ) { pDst[x] = (Pel)((pSrc[x - iSrcStride] + 3 * pDst[x] + 2) >> 2); } //left column (horizontal filter) for ( y = 1, iDstStride2 = iDstStride, iSrcStride2 = iSrcStride-1; y < iHeight; y++, iDstStride2+=iDstStride, iSrcStride2+=iSrcStride ) { pDst[iDstStride2] = (Pel)((pSrc[iSrcStride2] + 3 * pDst[iDstStride2] + 2) >> 2); } } return; } /* Static member function */ Bool TComPrediction::UseDPCMForFirstPassIntraEstimation(TComTU &rTu, const UInt uiDirMode) { return (rTu.getCU()->isRDPCMEnabled(rTu.GetAbsPartIdxTU()) ) && rTu.getCU()->getCUTransquantBypass(rTu.GetAbsPartIdxTU()) && (uiDirMode==HOR_IDX || uiDirMode==VER_IDX); } #if MCTS_ENC_CHECK Void getRefPUPartPos(TComDataCU* pcCU, TComMv& cMv, Int uiPartIdx, Int& ruiPredXLeft, Int& ruiPredYTop, Int& ruiPredXRight, Int& ruiPredYBottom, Int iWidth, Int iHeight) { ruiPredXLeft = pcCU->getCUPelX(); ruiPredYTop = pcCU->getCUPelY(); switch (pcCU->getPartitionSize(0)) { case SIZE_2NxN: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + (iHeight << 1); ruiPredYTop += iHeight; } break; case SIZE_Nx2N: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { ruiPredXRight = ruiPredXLeft + (iWidth << 1); ruiPredYBottom = ruiPredYTop + iHeight; ruiPredXLeft += iWidth; } break; case SIZE_NxN: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else if (uiPartIdx == 1) { ruiPredXRight = ruiPredXLeft + (iWidth << 1); ruiPredYBottom = ruiPredYTop + iHeight; ruiPredXLeft += iWidth; } else if (uiPartIdx == 2) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + (iHeight << 1); ruiPredYTop += iHeight; } else if (uiPartIdx == 3) { ruiPredXRight = ruiPredXLeft + (iWidth << 1); ruiPredYBottom = ruiPredYTop + (iHeight << 1); ruiPredXLeft += iWidth; ruiPredYTop += iHeight; } break; case SIZE_2NxnU: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + pcCU->getHeight(0); ruiPredYTop += (iHeight / 3); } break; case SIZE_2NxnD: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { Int oriHeight = iHeight << 2; ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + oriHeight; ruiPredYTop += (oriHeight >> 2) + (oriHeight >> 1); } break; case SIZE_nLx2N: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { ruiPredXRight = ruiPredXLeft + pcCU->getWidth(0); ruiPredYBottom = ruiPredYTop + iHeight; ruiPredXLeft += (iWidth / 3); } break; case SIZE_nRx2N: if (uiPartIdx == 0) { ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; } else { Int oriWidth = (iWidth << 2); ruiPredXRight = ruiPredXLeft + oriWidth; ruiPredYBottom = ruiPredYTop + iHeight; ruiPredXLeft += (oriWidth >> 2) + (oriWidth >> 1); } break; default: ruiPredXRight = ruiPredXLeft + iWidth; ruiPredYBottom = ruiPredYTop + iHeight; break; } ruiPredXLeft += (cMv.getHor() >> 2); ruiPredYTop += (cMv.getVer() >> 2); ruiPredXRight += (cMv.getHor() >> 2) - 1; ruiPredYBottom += (cMv.getVer() >> 2) - 1; } Bool checkMVPRange(TComMv& cMv, UInt ctuLength, UInt tileXPosInCtus, UInt tileYPosInCtus, UInt tileWidthtInCtus, UInt tileHeightInCtus, Int PredXLeft, Int PredXRight, Int PredYTop, Int PredYBottom, ChromaFormat chromaFormat) { // filter length of sub-sample generation filter to be considered const UInt LumaLTSampleOffset = 3; const UInt LumaRBSampleOffset = 4; const UInt CromaLTSampleoffset = 1; const UInt CromaRBSampleoffset = 2; // tile position in full pels const Int leftTopPelPosX = ctuLength * tileXPosInCtus; const Int leftTopPelPosY = ctuLength * tileYPosInCtus; const Int rightBottomPelPosX = ((tileWidthtInCtus + tileXPosInCtus) * ctuLength) - 1; const Int rightBottomPelPosY = ((tileHeightInCtus + tileYPosInCtus) * ctuLength) - 1; // Luma MV range check const Bool isFullPelHorLuma = (cMv.getHor() % 4 == 0); const Bool isFullPelVerLuma = (cMv.getVer() % 4 == 0); const Int lRangeXLeft = leftTopPelPosX + (isFullPelHorLuma ? 0 : LumaLTSampleOffset); const Int lRangeYTop = leftTopPelPosY + (isFullPelVerLuma ? 0 : LumaLTSampleOffset); const Int lRangeXRight = rightBottomPelPosX - (isFullPelHorLuma ? 0 : LumaRBSampleOffset); const Int lRangeYBottom = rightBottomPelPosY - (isFullPelVerLuma ? 0 : LumaRBSampleOffset); if (!(PredXLeft >= lRangeXLeft && PredXLeft <= lRangeXRight) || !(PredXRight >= lRangeXLeft && PredXRight <= lRangeXRight)) { return false; } else if (!(PredYTop >= lRangeYTop && PredYTop <= lRangeYBottom) || !(PredYBottom >= lRangeYTop && PredYBottom <= lRangeYBottom)) { return false; } if ((chromaFormat != CHROMA_444) && (chromaFormat != CHROMA_400)) { // Chroma MV range check const Bool isFullPelHorChroma = (cMv.getHor() % 8 == 0); const Bool isFullPelVerChroma = (cMv.getVer() % 8 == 0); const Int cRangeXLeft = leftTopPelPosX + (isFullPelHorChroma ? 0 : CromaLTSampleoffset); const Int cRangeYTop = leftTopPelPosY + (isFullPelVerChroma ? 0 : CromaLTSampleoffset); const Int cRangeXRight = rightBottomPelPosX - (isFullPelHorChroma ? 0 : CromaRBSampleoffset); const Int cRangeYBottom = rightBottomPelPosY - (isFullPelVerChroma ? 0 : CromaRBSampleoffset); if (!(PredXLeft >= cRangeXLeft && PredXLeft <= cRangeXRight) || !(PredXRight >= cRangeXLeft && PredXRight <= cRangeXRight)) { return false; } else if ((!(PredYTop >= cRangeYTop && PredYTop <= cRangeYBottom) || !(PredYBottom >= cRangeYTop && PredYBottom <= cRangeYBottom)) && (chromaFormat != CHROMA_422)) { return false; } } return true; } Bool TComPrediction::checkTMctsMvp(TComDataCU* pcCU, Int partIdx) { Int partWidth = 0; Int partHeight = 0; UInt partAddr = 0; UInt tileXPosInCtus = 0; UInt tileYPosInCtus = 0; UInt tileWidthtInCtus = 0; UInt tileHeightInCtus = 0; getTilePosition(pcCU, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus); const UInt ctuLength = pcCU->getPic()->getPicSym()->getSPS().getMaxCUWidth(); const ChromaFormat chromaFormat = pcCU->getPic()->getPicSym()->getSPS().getChromaFormatIdc(); Int predXLeft; Int predYTop; Int predXRight; Int predYBottom; if (partIdx >= 0) { pcCU->getPartIndexAndSize(partIdx, partAddr, partWidth, partHeight); if (xCheckIdenticalMotion(pcCU, partAddr)) { RefPicList eRefPicList = REF_PIC_LIST_0; TComMv cMv = pcCU->getCUMvField(eRefPicList)->getMv(partAddr); getRefPUPartPos(pcCU, cMv, partIdx, predXLeft, predYTop, predXRight, predYBottom, partWidth, partHeight); if (!checkMVPRange(cMv, ctuLength, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus, predXLeft, predXRight, predYTop, predYBottom, chromaFormat)) { return false; } } else { for (UInt refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); TComMv cMv = pcCU->getCUMvField(eRefPicList)->getMv(partAddr); getRefPUPartPos(pcCU, cMv, partIdx, predXLeft, predYTop, predXRight, predYBottom, partWidth, partHeight); if (!checkMVPRange(cMv, ctuLength, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus, predXLeft, predXRight, predYTop, predYBottom, chromaFormat)) { return false; } } } return true; } for (partIdx = 0; partIdx < pcCU->getNumPartitions(); partIdx++) { pcCU->getPartIndexAndSize(partIdx, partAddr, partWidth, partHeight); if (xCheckIdenticalMotion(pcCU, partAddr)) { RefPicList eRefPicList = REF_PIC_LIST_0; TComMv cMv = pcCU->getCUMvField(eRefPicList)->getMv(partAddr); getRefPUPartPos(pcCU, cMv, partIdx, predXLeft, predYTop, predXRight, predYBottom, partWidth, partHeight); if (!checkMVPRange(cMv, ctuLength, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus, predXLeft, predXRight, predYTop, predYBottom, chromaFormat)) { return false; } } else { for (UInt refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); TComMv cMv = pcCU->getCUMvField(eRefPicList)->getMv(partAddr); getRefPUPartPos(pcCU, cMv, partIdx, predXLeft, predYTop, predXRight, predYBottom, partWidth, partHeight); if (!checkMVPRange(cMv, ctuLength, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus, predXLeft, predXRight, predYTop, predYBottom, chromaFormat)) { return false; } } } } return true; } #endif //! \} HM-HM-18.0/source/Lib/TLibCommon/TComPrediction.h000066400000000000000000000150351442026013100213120ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComPrediction.h \brief prediction class (header) */ #ifndef __TCOMPREDICTION__ #define __TCOMPREDICTION__ // Include files #include "TComYuv.h" #include "TComInterpolationFilter.h" #include "TComWeightPrediction.h" // forward declaration class TComMv; class TComTU; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// prediction class typedef enum PRED_BUF_E { PRED_BUF_UNFILTERED=0, PRED_BUF_FILTERED=1, NUM_PRED_BUF=2 } PRED_BUF; static const UInt MAX_INTRA_FILTER_DEPTHS=5; class TComPrediction : public TComWeightPrediction { private: static const UChar m_aucIntraFilter[MAX_NUM_CHANNEL_TYPE][MAX_INTRA_FILTER_DEPTHS]; protected: Pel* m_piYuvExt[MAX_NUM_COMPONENT][NUM_PRED_BUF]; Int m_iYuvExtSize; TComYuv m_acYuvPred[NUM_REF_PIC_LIST_01]; TComYuv m_cYuvPredTemp; TComYuv m_filteredBlock[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS]; TComYuv m_filteredBlockTmp[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS]; TComInterpolationFilter m_if; Pel* m_pLumaRecBuffer; ///< array for downsampled reconstructed luma sample Int m_iLumaRecStride; ///< stride of #m_pLumaRecBuffer array Void xPredIntraAng ( Int bitDepth, const Pel* pSrc, Int srcStride, Pel* pDst, Int dstStride, UInt width, UInt height, ChannelType channelType, UInt dirMode, const Bool bEnableEdgeFilters ); Void xPredIntraPlanar ( const Pel* pSrc, Int srcStride, Pel* rpDst, Int dstStride, UInt width, UInt height ); // motion compensation functions Void xPredInterUni ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, RefPicList eRefPicList, TComYuv* pcYuvPred, Bool bi=false ); Void xPredInterBi ( TComDataCU* pcCU, UInt uiPartAddr, Int iWidth, Int iHeight, TComYuv* pcYuvPred ); Void xPredInterBlk(const ComponentID compID, TComDataCU *cu, TComPicYuv *refPic, UInt partAddr, TComMv *mv, Int width, Int height, TComYuv *dstPic, Bool bi, const Int bitDepth ); Void xWeightedAverage ( TComYuv* pcYuvSrc0, TComYuv* pcYuvSrc1, Int iRefIdx0, Int iRefIdx1, UInt uiPartAddr, Int iWidth, Int iHeight, TComYuv* pcYuvDst, const BitDepths &clipBitDepths ); Void xGetLLSPrediction ( const Pel* pSrc0, Int iSrcStride, Pel* pDst0, Int iDstStride, UInt uiWidth, UInt uiHeight, UInt uiExt0, const ChromaFormat chFmt DEBUG_STRING_FN_DECLARE(sDebug) ); Void xDCPredFiltering( const Pel* pSrc, Int iSrcStride, Pel* pDst, Int iDstStride, Int iWidth, Int iHeight, ChannelType channelType ); Bool xCheckIdenticalMotion ( TComDataCU* pcCU, UInt PartAddr); Void destroy(); public: TComPrediction(); virtual ~TComPrediction(); Void initTempBuff(ChromaFormat chromaFormatIDC); ChromaFormat getChromaFormat() const { return m_cYuvPredTemp.getChromaFormat(); } // inter Void motionCompensation ( TComDataCU* pcCU, TComYuv* pcYuvPred, RefPicList eRefPicList = REF_PIC_LIST_X, Int iPartIdx = -1 ); // motion vector prediction Void getMvPredAMVP ( TComDataCU* pcCU, UInt uiPartIdx, UInt uiPartAddr, RefPicList eRefPicList, TComMv& rcMvPred ); // Angular Intra Void predIntraAng ( const ComponentID compID, UInt uiDirMode, Pel *piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM = false ); Pel predIntraGetPredValDC ( const Pel* pSrc, Int iSrcStride, UInt iWidth, UInt iHeight); Pel* getPredictorPtr ( const ComponentID compID, const Bool bUseFilteredPredictions ) { return m_piYuvExt[compID][bUseFilteredPredictions?PRED_BUF_FILTERED:PRED_BUF_UNFILTERED]; } // This function is actually still in TComPattern.cpp /// set parameters from CU data for accessing intra data Void initIntraPatternChType ( TComTU &rTu, const ComponentID compID, const Bool bFilterRefSamples DEBUG_STRING_FN_DECLARE(sDebug) ); static Bool filteringIntraReferenceSamples(const ComponentID compID, UInt uiDirMode, UInt uiTuChWidth, UInt uiTuChHeight, const ChromaFormat chFmt, const Bool intraReferenceSmoothingDisabled); static Bool UseDPCMForFirstPassIntraEstimation(TComTU &rTu, const UInt uiDirMode); #if MCTS_ENC_CHECK Bool checkTMctsMvp(TComDataCU* pcCU, Int partIdx = -1); #endif }; //! \} #endif // __TCOMPREDICTION__ HM-HM-18.0/source/Lib/TLibCommon/TComRdCost.cpp000066400000000000000000001764111442026013100207510ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRdCost.cpp \brief RD cost computation class */ #include #include #include #include "TComRom.h" #include "TComRdCost.h" #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) #include #include #endif //! \ingroup TLibCommon //! \{ TComRdCost::TComRdCost() { init(); } TComRdCost::~TComRdCost() { } // Calculate RD functions Double TComRdCost::calcRdCost( Double numBits, Distortion distortion, DFunc eDFunc ) { Double lambda = 1.0; switch ( eDFunc ) { case DF_SSE: assert(0); break; case DF_SAD: lambda = m_dLambdaMotionSAD[0]; // 0 is valid, because for lossless blocks, the cost equation is modified to compensate. break; case DF_DEFAULT: lambda = m_dLambda; break; case DF_SSE_FRAME: lambda = m_dFrameLambda; break; default: assert (0); break; } if (eDFunc == DF_SAD) { if (m_costMode != COST_STANDARD_LOSSY) { return ((distortion * 65536.0) / lambda) + numBits; // all lossless costs would have uiDistortion=0, and therefore this cost function can be used. } else { return distortion + (((numBits * lambda) ) / 65536.0); } } else { if (m_costMode != COST_STANDARD_LOSSY) { return (distortion / lambda) + numBits; // all lossless costs would have uiDistortion=0, and therefore this cost function can be used. } else { return distortion + (numBits * lambda); } } } Void TComRdCost::setLambda( Double dLambda, const BitDepths &bitDepths ) { m_dLambda = dLambda; m_sqrtLambda = sqrt(m_dLambda); m_dLambdaMotionSAD[0] = 65536.0 * m_sqrtLambda; m_dLambdaMotionSSE[0] = 65536.0 * m_dLambda; #if FULL_NBIT dLambda = 0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12) / 3.0)); #else dLambda = 0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12 - 6 * (bitDepths.recon[CHANNEL_TYPE_LUMA] - 8)) / 3.0)); #endif m_dLambdaMotionSAD[1] = 65536.0 * sqrt(dLambda); m_dLambdaMotionSSE[1] = 65536.0 * dLambda; } // Initalize Function Pointer by [eDFunc] Void TComRdCost::init() { m_afpDistortFunc[DF_DEFAULT] = NULL; // for DF_DEFAULT m_afpDistortFunc[DF_SSE ] = TComRdCost::xGetSSE; m_afpDistortFunc[DF_SSE4 ] = TComRdCost::xGetSSE4; m_afpDistortFunc[DF_SSE8 ] = TComRdCost::xGetSSE8; m_afpDistortFunc[DF_SSE16 ] = TComRdCost::xGetSSE16; m_afpDistortFunc[DF_SSE32 ] = TComRdCost::xGetSSE32; m_afpDistortFunc[DF_SSE64 ] = TComRdCost::xGetSSE64; m_afpDistortFunc[DF_SSE16N ] = TComRdCost::xGetSSE16N; m_afpDistortFunc[DF_SAD ] = TComRdCost::xGetSAD; m_afpDistortFunc[DF_SAD4 ] = TComRdCost::xGetSAD4; m_afpDistortFunc[DF_SAD8 ] = TComRdCost::xGetSAD8; m_afpDistortFunc[DF_SAD16 ] = TComRdCost::xGetSAD16; m_afpDistortFunc[DF_SAD32 ] = TComRdCost::xGetSAD32; m_afpDistortFunc[DF_SAD64 ] = TComRdCost::xGetSAD64; m_afpDistortFunc[DF_SAD16N ] = TComRdCost::xGetSAD16N; m_afpDistortFunc[DF_SADS ] = TComRdCost::xGetSAD; m_afpDistortFunc[DF_SADS4 ] = TComRdCost::xGetSAD4; m_afpDistortFunc[DF_SADS8 ] = TComRdCost::xGetSAD8; m_afpDistortFunc[DF_SADS16 ] = TComRdCost::xGetSAD16; m_afpDistortFunc[DF_SADS32 ] = TComRdCost::xGetSAD32; m_afpDistortFunc[DF_SADS64 ] = TComRdCost::xGetSAD64; m_afpDistortFunc[DF_SADS16N] = TComRdCost::xGetSAD16N; m_afpDistortFunc[DF_SAD12 ] = TComRdCost::xGetSAD12; m_afpDistortFunc[DF_SAD24 ] = TComRdCost::xGetSAD24; m_afpDistortFunc[DF_SAD48 ] = TComRdCost::xGetSAD48; m_afpDistortFunc[DF_SADS12 ] = TComRdCost::xGetSAD12; m_afpDistortFunc[DF_SADS24 ] = TComRdCost::xGetSAD24; m_afpDistortFunc[DF_SADS48 ] = TComRdCost::xGetSAD48; m_afpDistortFunc[DF_HADS ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS4 ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS8 ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS16 ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS32 ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS64 ] = TComRdCost::xGetHADs; m_afpDistortFunc[DF_HADS16N] = TComRdCost::xGetHADs; m_costMode = COST_STANDARD_LOSSY; m_motionLambda = 0; m_iCostScale = 0; } // Static member function UInt TComRdCost::xGetExpGolombNumberOfBits( Int iVal ) { assert(iVal != std::numeric_limits::min()); UInt uiLength = 1; UInt uiTemp = ( iVal <= 0) ? (UInt(-iVal)<<1)+1: UInt(iVal<<1); while ( 1 != uiTemp ) { uiTemp >>= 1; uiLength += 2; } return uiLength; } Void TComRdCost::setDistParam( UInt uiBlkWidth, UInt uiBlkHeight, DFunc eDFunc, DistParam& rcDistParam ) { // set Block Width / Height rcDistParam.iCols = uiBlkWidth; rcDistParam.iRows = uiBlkHeight; rcDistParam.DistFunc = m_afpDistortFunc[eDFunc + g_aucConvertToBit[ rcDistParam.iCols ] + 1 ]; // initialize rcDistParam.iSubShift = 0; rcDistParam.m_maximumDistortionForEarlyExit = std::numeric_limits::max(); } // Setting the Distortion Parameter for Inter (ME) Void TComRdCost::setDistParam( const TComPattern* const pcPatternKey, const Pel* piRefY, Int iRefStride, DistParam& rcDistParam ) { // set Original & Curr Pointer / Stride rcDistParam.pOrg = pcPatternKey->getROIY(); rcDistParam.pCur = piRefY; rcDistParam.iStrideOrg = pcPatternKey->getPatternLStride(); rcDistParam.iStrideCur = iRefStride; // set Block Width / Height rcDistParam.iCols = pcPatternKey->getROIYWidth(); rcDistParam.iRows = pcPatternKey->getROIYHeight(); rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD + g_aucConvertToBit[ rcDistParam.iCols ] + 1 ]; rcDistParam.m_maximumDistortionForEarlyExit = std::numeric_limits::max(); if (rcDistParam.iCols == 12) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD12]; } else if (rcDistParam.iCols == 24) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD24]; } else if (rcDistParam.iCols == 48) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD48]; } // initialize rcDistParam.iSubShift = 0; } // Setting the Distortion Parameter for Inter (subpel ME with step) Void TComRdCost::setDistParam( const TComPattern* const pcPatternKey, const Pel* piRefY, Int iRefStride, Int iStep, DistParam& rcDistParam, Bool bHADME ) { // set Original & Curr Pointer / Stride rcDistParam.pOrg = pcPatternKey->getROIY(); rcDistParam.pCur = piRefY; rcDistParam.iStrideOrg = pcPatternKey->getPatternLStride(); rcDistParam.iStrideCur = iRefStride * iStep; // set Step for interpolated buffer rcDistParam.iStep = iStep; // set Block Width / Height rcDistParam.iCols = pcPatternKey->getROIYWidth(); rcDistParam.iRows = pcPatternKey->getROIYHeight(); rcDistParam.m_maximumDistortionForEarlyExit = std::numeric_limits::max(); // set distortion function if ( !bHADME ) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SADS + g_aucConvertToBit[ rcDistParam.iCols ] + 1 ]; if (rcDistParam.iCols == 12) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SADS12]; } else if (rcDistParam.iCols == 24) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SADS24]; } else if (rcDistParam.iCols == 48) { rcDistParam.DistFunc = m_afpDistortFunc[DF_SADS48]; } } else { rcDistParam.DistFunc = m_afpDistortFunc[DF_HADS + g_aucConvertToBit[ rcDistParam.iCols ] + 1 ]; } // initialize rcDistParam.iSubShift = 0; } Void TComRdCost::setDistParam( DistParam& rcDP, Int bitDepth, const Pel* p1, Int iStride1, const Pel* p2, Int iStride2, Int iWidth, Int iHeight, Bool bHadamard ) { rcDP.pOrg = p1; rcDP.pCur = p2; rcDP.iStrideOrg = iStride1; rcDP.iStrideCur = iStride2; rcDP.iCols = iWidth; rcDP.iRows = iHeight; rcDP.iStep = 1; rcDP.iSubShift = 0; rcDP.bitDepth = bitDepth; rcDP.DistFunc = m_afpDistortFunc[ ( bHadamard ? DF_HADS : DF_SADS ) + g_aucConvertToBit[ iWidth ] + 1 ]; rcDP.m_maximumDistortionForEarlyExit = std::numeric_limits::max(); } Distortion TComRdCost::calcHAD( Int bitDepth, const Pel* pi0, Int iStride0, const Pel* pi1, Int iStride1, Int iWidth, Int iHeight ) { Distortion uiSum = 0; Int x, y; if ( ( (iWidth % 8) == 0 ) && ( (iHeight % 8) == 0 ) ) { for ( y=0; y> DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8) ); } Distortion TComRdCost::getDistPart( Int bitDepth, const Pel* piCur, Int iCurStride, const Pel* piOrg, Int iOrgStride, UInt uiBlkWidth, UInt uiBlkHeight, const ComponentID compID, DFunc eDFunc ) { DistParam cDtParam; setDistParam( uiBlkWidth, uiBlkHeight, eDFunc, cDtParam ); cDtParam.pOrg = piOrg; cDtParam.pCur = piCur; cDtParam.iStrideOrg = iOrgStride; cDtParam.iStrideCur = iCurStride; cDtParam.iStep = 1; cDtParam.bApplyWeight = false; cDtParam.compIdx = MAX_NUM_COMPONENT; // just for assert: to be sure it was set before use cDtParam.bitDepth = bitDepth; if (isChroma(compID)) { return ((Distortion) (m_distortionWeight[compID] * cDtParam.DistFunc( &cDtParam ))); } else { return cDtParam.DistFunc( &cDtParam ); } } // ==================================================================================================================== // Distortion functions // ==================================================================================================================== #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) inline Int simdSADLine4n16b( const Pel * piOrg , const Pel * piCur , Int nWidth ) { // internal bit-depth must be 12-bit or lower assert( !( nWidth & 0x03 ) ); __m128i org , cur , abs , sum; sum = _mm_setzero_si128(); for( Int n = 0 ; n < nWidth ; n += 4 ) { org = _mm_loadl_epi64( ( __m128i* )( piOrg + n ) ); cur = _mm_loadl_epi64( ( __m128i* )( piCur + n ) ); abs = _mm_subs_epi16( _mm_max_epi16( org , cur ) , _mm_min_epi16( org , cur ) ); sum = _mm_adds_epu16( abs , sum ); } __m128i zero = _mm_setzero_si128(); sum = _mm_unpacklo_epi16( sum , zero ); sum = _mm_add_epi32( sum , _mm_shuffle_epi32( sum , _MM_SHUFFLE( 2 , 3 , 0 , 1 ) ) ); sum = _mm_add_epi32( sum , _mm_shuffle_epi32( sum , _MM_SHUFFLE( 1 , 0 , 3 , 2 ) ) ); return( _mm_cvtsi128_si32( sum ) ); } inline Int simdSADLine8n16b( const Pel * piOrg , const Pel * piCur , Int nWidth ) { // internal bit-depth must be 12-bit or lower assert( !( nWidth & 0x07 ) ); __m128i org , cur , abs , sum; sum = _mm_setzero_si128(); for( Int n = 0 ; n < nWidth ; n += 8 ) { org = _mm_loadu_si128( ( __m128i* )( piOrg + n ) ); cur = _mm_loadu_si128( ( __m128i* )( piCur + n ) ); abs = _mm_subs_epi16( _mm_max_epi16( org , cur ) , _mm_min_epi16( org , cur ) ); sum = _mm_adds_epu16( abs , sum ); } __m128i zero = _mm_setzero_si128(); __m128i hi = _mm_unpackhi_epi16( sum , zero ); __m128i lo = _mm_unpacklo_epi16( sum , zero ); sum = _mm_add_epi32( lo , hi ); sum = _mm_add_epi32( sum , _mm_shuffle_epi32( sum , _MM_SHUFFLE( 2 , 3 , 0 , 1 ) ) ); sum = _mm_add_epi32( sum , _mm_shuffle_epi32( sum , _MM_SHUFFLE( 1 , 0 , 3 , 2 ) ) ); return( _mm_cvtsi128_si32( sum ) ); } inline Void simd8x8Transpose32b( __m128i * pBuffer ) { __m128 tmp[16]; for( Int n = 0 ; n < 16 ; n++ ) { tmp[n] = _mm_castsi128_ps( pBuffer[n] ); } _MM_TRANSPOSE4_PS( tmp[0] , tmp[2] , tmp[4] , tmp[6] ); _MM_TRANSPOSE4_PS( tmp[1] , tmp[3] , tmp[5] , tmp[7] ); _MM_TRANSPOSE4_PS( tmp[8] , tmp[10] , tmp[12] , tmp[14] ); _MM_TRANSPOSE4_PS( tmp[9] , tmp[11] , tmp[13] , tmp[15] ); for( Int n = 0 ; n < 8 ; n += 2 ) { pBuffer[n] = _mm_castps_si128( tmp[n] ); pBuffer[n+1] = _mm_castps_si128( tmp[n+8] ); pBuffer[n+8] = _mm_castps_si128( tmp[n+1] ); pBuffer[n+9] = _mm_castps_si128( tmp[n+9] ); } } #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION > 40600 && GCC_VERSION < 40700 __attribute__((optimize("no-tree-vrp"))) #endif #endif Void simd8x8HAD1D32b( __m128i * pInput , __m128i * pOutput ) { __m128i m1[8][2] , m2[8][2]; m2[0][0] = _mm_add_epi32( pInput[0] ,pInput[8 ] ); m2[0][1] = _mm_add_epi32( pInput[1] ,pInput[9 ] ); m2[1][0] = _mm_add_epi32( pInput[2] ,pInput[10] ); m2[1][1] = _mm_add_epi32( pInput[3] ,pInput[11] ); m2[2][0] = _mm_add_epi32( pInput[4] ,pInput[12] ); m2[2][1] = _mm_add_epi32( pInput[5] ,pInput[13] ); m2[3][0] = _mm_add_epi32( pInput[6] ,pInput[14] ); m2[3][1] = _mm_add_epi32( pInput[7] ,pInput[15] ); m2[4][0] = _mm_sub_epi32( pInput[0] ,pInput[8 ] ); m2[4][1] = _mm_sub_epi32( pInput[1] ,pInput[9 ] ); m2[5][0] = _mm_sub_epi32( pInput[2] ,pInput[10] ); m2[5][1] = _mm_sub_epi32( pInput[3] ,pInput[11] ); m2[6][0] = _mm_sub_epi32( pInput[4] ,pInput[12] ); m2[6][1] = _mm_sub_epi32( pInput[5] ,pInput[13] ); m2[7][0] = _mm_sub_epi32( pInput[6] ,pInput[14] ); m2[7][1] = _mm_sub_epi32( pInput[7] ,pInput[15] ); m1[0][0] = _mm_add_epi32( m2[0][0] , m2[2][0] ); m1[0][1] = _mm_add_epi32( m2[0][1] , m2[2][1] ); m1[1][0] = _mm_add_epi32( m2[1][0] , m2[3][0] ); m1[1][1] = _mm_add_epi32( m2[1][1] , m2[3][1] ); m1[2][0] = _mm_sub_epi32( m2[0][0] , m2[2][0] ); m1[2][1] = _mm_sub_epi32( m2[0][1] , m2[2][1] ); m1[3][0] = _mm_sub_epi32( m2[1][0] , m2[3][0] ); m1[3][1] = _mm_sub_epi32( m2[1][1] , m2[3][1] ); m1[4][0] = _mm_add_epi32( m2[4][0] , m2[6][0] ); m1[4][1] = _mm_add_epi32( m2[4][1] , m2[6][1] ); m1[5][0] = _mm_add_epi32( m2[5][0] , m2[7][0] ); m1[5][1] = _mm_add_epi32( m2[5][1] , m2[7][1] ); m1[6][0] = _mm_sub_epi32( m2[4][0] , m2[6][0] ); m1[6][1] = _mm_sub_epi32( m2[4][1] , m2[6][1] ); m1[7][0] = _mm_sub_epi32( m2[5][0] , m2[7][0] ); m1[7][1] = _mm_sub_epi32( m2[5][1] , m2[7][1] ); pInput[0 ] = _mm_add_epi32( m1[0][0] , m1[1][0] ); pInput[1 ] = _mm_add_epi32( m1[0][1] , m1[1][1] ); pInput[2 ] = _mm_sub_epi32( m1[0][0] , m1[1][0] ); pInput[3 ] = _mm_sub_epi32( m1[0][1] , m1[1][1] ); pInput[4 ] = _mm_add_epi32( m1[2][0] , m1[3][0] ); pInput[5 ] = _mm_add_epi32( m1[2][1] , m1[3][1] ); pInput[6 ] = _mm_sub_epi32( m1[2][0] , m1[3][0] ); pInput[7 ] = _mm_sub_epi32( m1[2][1] , m1[3][1] ); pInput[8 ] = _mm_add_epi32( m1[4][0] , m1[5][0] ); pInput[9 ] = _mm_add_epi32( m1[4][1] , m1[5][1] ); pInput[10] = _mm_sub_epi32( m1[4][0] , m1[5][0] ); pInput[11] = _mm_sub_epi32( m1[4][1] , m1[5][1] ); pInput[12] = _mm_add_epi32( m1[6][0] , m1[7][0] ); pInput[13] = _mm_add_epi32( m1[6][1] , m1[7][1] ); pInput[14] = _mm_sub_epi32( m1[6][0] , m1[7][0] ); pInput[15] = _mm_sub_epi32( m1[6][1] , m1[7][1] ); } inline __m128i simdAbs32b( __m128i m ) { const __m128i zero = _mm_setzero_si128(); __m128i tmp = _mm_sub_epi32( zero , m ); __m128i mask = _mm_cmpgt_epi32( m , tmp ); return( _mm_or_si128( _mm_and_si128( mask , m ) , _mm_andnot_si128( mask , tmp ) ) ); } UInt simdHADs8x8( const Pel * piOrg, const Pel * piCur, Int iStrideOrg, Int iStrideCur ) { __m128i mmDiff[8][2]; __m128i mmZero = _mm_setzero_si128(); for( Int n = 0 ; n < 8 ; n++ , piOrg += iStrideOrg , piCur += iStrideCur ) { __m128i diff = _mm_sub_epi16( _mm_loadu_si128( ( __m128i* )piOrg ) , _mm_loadu_si128( ( __m128i* )piCur ) ); // sign extension __m128i mask = _mm_cmplt_epi16( diff , mmZero ); mmDiff[n][0] = _mm_unpacklo_epi16( diff , mask ); mmDiff[n][1] = _mm_unpackhi_epi16( diff , mask ); } // transpose simd8x8Transpose32b( &mmDiff[0][0] ); // horizontal simd8x8HAD1D32b( &mmDiff[0][0] , &mmDiff[0][0] ); // transpose simd8x8Transpose32b( &mmDiff[0][0] ); // vertical simd8x8HAD1D32b( &mmDiff[0][0] , &mmDiff[0][0] ); __m128i mmSum = _mm_setzero_si128(); for( Int n = 0 ; n < 8 ; n++ ) { mmSum = _mm_add_epi32( mmSum , simdAbs32b( mmDiff[n][0] ) ); mmSum = _mm_add_epi32( mmSum , simdAbs32b( mmDiff[n][1] ) ); } mmSum = _mm_add_epi32( mmSum , _mm_shuffle_epi32( mmSum , _MM_SHUFFLE( 2 , 3 , 0 , 1 ) ) ); mmSum = _mm_add_epi32( mmSum , _mm_shuffle_epi32( mmSum , _MM_SHUFFLE( 1 , 0 , 3 , 2 ) ) ); UInt sad = _mm_cvtsi128_si32( mmSum ); sad = ( sad + 2 ) >> 2; return( sad ); } #endif // -------------------------------------------------------------------------------------------------------------------- // SAD // -------------------------------------------------------------------------------------------------------------------- Distortion TComRdCost::xGetSAD( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; const Int iCols = pcDtParam->iCols; const Int iStrideCur = pcDtParam->iStrideCur; const Int iStrideOrg = pcDtParam->iStrideOrg; const UInt distortionShift = DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth - 8); Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { if( ( iCols & 0x07 ) == 0 ) { for( Int iRows = pcDtParam->iRows ; iRows != 0; iRows-- ) { uiSum += simdSADLine8n16b( piOrg , piCur , iCols ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { for( Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { uiSum += simdSADLine4n16b( piOrg , piCur , iCols ); piOrg += iStrideOrg; piCur += iStrideCur; } } } else { #endif for(Int iRows = pcDtParam->iRows ; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { uiSum += abs( piOrg[n] - piCur[n] ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift )) { return ( uiSum >> distortionShift ); } piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif return ( uiSum >> distortionShift ); } Distortion TComRdCost::xGetSAD4( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine4n16b( piOrg , piCur , 4 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD8( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 8 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD16( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 16 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); uiSum += abs( piOrg[12] - piCur[12] ); uiSum += abs( piOrg[13] - piCur[13] ); uiSum += abs( piOrg[14] - piCur[14] ); uiSum += abs( piOrg[15] - piCur[15] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD12( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); piOrg += iStrideOrg; piCur += iStrideCur; } uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD16N( DistParam* pcDtParam ) { const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iCols = pcDtParam->iCols; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , iCols ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { for (Int n = 0; n < iCols; n+=16 ) { uiSum += abs( piOrg[n+ 0] - piCur[n+ 0] ); uiSum += abs( piOrg[n+ 1] - piCur[n+ 1] ); uiSum += abs( piOrg[n+ 2] - piCur[n+ 2] ); uiSum += abs( piOrg[n+ 3] - piCur[n+ 3] ); uiSum += abs( piOrg[n+ 4] - piCur[n+ 4] ); uiSum += abs( piOrg[n+ 5] - piCur[n+ 5] ); uiSum += abs( piOrg[n+ 6] - piCur[n+ 6] ); uiSum += abs( piOrg[n+ 7] - piCur[n+ 7] ); uiSum += abs( piOrg[n+ 8] - piCur[n+ 8] ); uiSum += abs( piOrg[n+ 9] - piCur[n+ 9] ); uiSum += abs( piOrg[n+10] - piCur[n+10] ); uiSum += abs( piOrg[n+11] - piCur[n+11] ); uiSum += abs( piOrg[n+12] - piCur[n+12] ); uiSum += abs( piOrg[n+13] - piCur[n+13] ); uiSum += abs( piOrg[n+14] - piCur[n+14] ); uiSum += abs( piOrg[n+15] - piCur[n+15] ); } piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD32( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 32 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); uiSum += abs( piOrg[12] - piCur[12] ); uiSum += abs( piOrg[13] - piCur[13] ); uiSum += abs( piOrg[14] - piCur[14] ); uiSum += abs( piOrg[15] - piCur[15] ); uiSum += abs( piOrg[16] - piCur[16] ); uiSum += abs( piOrg[17] - piCur[17] ); uiSum += abs( piOrg[18] - piCur[18] ); uiSum += abs( piOrg[19] - piCur[19] ); uiSum += abs( piOrg[20] - piCur[20] ); uiSum += abs( piOrg[21] - piCur[21] ); uiSum += abs( piOrg[22] - piCur[22] ); uiSum += abs( piOrg[23] - piCur[23] ); uiSum += abs( piOrg[24] - piCur[24] ); uiSum += abs( piOrg[25] - piCur[25] ); uiSum += abs( piOrg[26] - piCur[26] ); uiSum += abs( piOrg[27] - piCur[27] ); uiSum += abs( piOrg[28] - piCur[28] ); uiSum += abs( piOrg[29] - piCur[29] ); uiSum += abs( piOrg[30] - piCur[30] ); uiSum += abs( piOrg[31] - piCur[31] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD24( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 24 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); uiSum += abs( piOrg[12] - piCur[12] ); uiSum += abs( piOrg[13] - piCur[13] ); uiSum += abs( piOrg[14] - piCur[14] ); uiSum += abs( piOrg[15] - piCur[15] ); uiSum += abs( piOrg[16] - piCur[16] ); uiSum += abs( piOrg[17] - piCur[17] ); uiSum += abs( piOrg[18] - piCur[18] ); uiSum += abs( piOrg[19] - piCur[19] ); uiSum += abs( piOrg[20] - piCur[20] ); uiSum += abs( piOrg[21] - piCur[21] ); uiSum += abs( piOrg[22] - piCur[22] ); uiSum += abs( piOrg[23] - piCur[23] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD64( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 64 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); uiSum += abs( piOrg[12] - piCur[12] ); uiSum += abs( piOrg[13] - piCur[13] ); uiSum += abs( piOrg[14] - piCur[14] ); uiSum += abs( piOrg[15] - piCur[15] ); uiSum += abs( piOrg[16] - piCur[16] ); uiSum += abs( piOrg[17] - piCur[17] ); uiSum += abs( piOrg[18] - piCur[18] ); uiSum += abs( piOrg[19] - piCur[19] ); uiSum += abs( piOrg[20] - piCur[20] ); uiSum += abs( piOrg[21] - piCur[21] ); uiSum += abs( piOrg[22] - piCur[22] ); uiSum += abs( piOrg[23] - piCur[23] ); uiSum += abs( piOrg[24] - piCur[24] ); uiSum += abs( piOrg[25] - piCur[25] ); uiSum += abs( piOrg[26] - piCur[26] ); uiSum += abs( piOrg[27] - piCur[27] ); uiSum += abs( piOrg[28] - piCur[28] ); uiSum += abs( piOrg[29] - piCur[29] ); uiSum += abs( piOrg[30] - piCur[30] ); uiSum += abs( piOrg[31] - piCur[31] ); uiSum += abs( piOrg[32] - piCur[32] ); uiSum += abs( piOrg[33] - piCur[33] ); uiSum += abs( piOrg[34] - piCur[34] ); uiSum += abs( piOrg[35] - piCur[35] ); uiSum += abs( piOrg[36] - piCur[36] ); uiSum += abs( piOrg[37] - piCur[37] ); uiSum += abs( piOrg[38] - piCur[38] ); uiSum += abs( piOrg[39] - piCur[39] ); uiSum += abs( piOrg[40] - piCur[40] ); uiSum += abs( piOrg[41] - piCur[41] ); uiSum += abs( piOrg[42] - piCur[42] ); uiSum += abs( piOrg[43] - piCur[43] ); uiSum += abs( piOrg[44] - piCur[44] ); uiSum += abs( piOrg[45] - piCur[45] ); uiSum += abs( piOrg[46] - piCur[46] ); uiSum += abs( piOrg[47] - piCur[47] ); uiSum += abs( piOrg[48] - piCur[48] ); uiSum += abs( piOrg[49] - piCur[49] ); uiSum += abs( piOrg[50] - piCur[50] ); uiSum += abs( piOrg[51] - piCur[51] ); uiSum += abs( piOrg[52] - piCur[52] ); uiSum += abs( piOrg[53] - piCur[53] ); uiSum += abs( piOrg[54] - piCur[54] ); uiSum += abs( piOrg[55] - piCur[55] ); uiSum += abs( piOrg[56] - piCur[56] ); uiSum += abs( piOrg[57] - piCur[57] ); uiSum += abs( piOrg[58] - piCur[58] ); uiSum += abs( piOrg[59] - piCur[59] ); uiSum += abs( piOrg[60] - piCur[60] ); uiSum += abs( piOrg[61] - piCur[61] ); uiSum += abs( piOrg[62] - piCur[62] ); uiSum += abs( piOrg[63] - piCur[63] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } Distortion TComRdCost::xGetSAD48( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSADw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iSubShift = pcDtParam->iSubShift; Int iSubStep = ( 1 << iSubShift ); Int iStrideCur = pcDtParam->iStrideCur*iSubStep; Int iStrideOrg = pcDtParam->iStrideOrg*iSubStep; Distortion uiSum = 0; #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( pcDtParam->bitDepth <= 10 ) { for( ; iRows != 0; iRows-=iSubStep ) { uiSum += simdSADLine8n16b( piOrg , piCur , 48 ); piOrg += iStrideOrg; piCur += iStrideCur; } } else { #endif for( ; iRows != 0; iRows-=iSubStep ) { uiSum += abs( piOrg[0] - piCur[0] ); uiSum += abs( piOrg[1] - piCur[1] ); uiSum += abs( piOrg[2] - piCur[2] ); uiSum += abs( piOrg[3] - piCur[3] ); uiSum += abs( piOrg[4] - piCur[4] ); uiSum += abs( piOrg[5] - piCur[5] ); uiSum += abs( piOrg[6] - piCur[6] ); uiSum += abs( piOrg[7] - piCur[7] ); uiSum += abs( piOrg[8] - piCur[8] ); uiSum += abs( piOrg[9] - piCur[9] ); uiSum += abs( piOrg[10] - piCur[10] ); uiSum += abs( piOrg[11] - piCur[11] ); uiSum += abs( piOrg[12] - piCur[12] ); uiSum += abs( piOrg[13] - piCur[13] ); uiSum += abs( piOrg[14] - piCur[14] ); uiSum += abs( piOrg[15] - piCur[15] ); uiSum += abs( piOrg[16] - piCur[16] ); uiSum += abs( piOrg[17] - piCur[17] ); uiSum += abs( piOrg[18] - piCur[18] ); uiSum += abs( piOrg[19] - piCur[19] ); uiSum += abs( piOrg[20] - piCur[20] ); uiSum += abs( piOrg[21] - piCur[21] ); uiSum += abs( piOrg[22] - piCur[22] ); uiSum += abs( piOrg[23] - piCur[23] ); uiSum += abs( piOrg[24] - piCur[24] ); uiSum += abs( piOrg[25] - piCur[25] ); uiSum += abs( piOrg[26] - piCur[26] ); uiSum += abs( piOrg[27] - piCur[27] ); uiSum += abs( piOrg[28] - piCur[28] ); uiSum += abs( piOrg[29] - piCur[29] ); uiSum += abs( piOrg[30] - piCur[30] ); uiSum += abs( piOrg[31] - piCur[31] ); uiSum += abs( piOrg[32] - piCur[32] ); uiSum += abs( piOrg[33] - piCur[33] ); uiSum += abs( piOrg[34] - piCur[34] ); uiSum += abs( piOrg[35] - piCur[35] ); uiSum += abs( piOrg[36] - piCur[36] ); uiSum += abs( piOrg[37] - piCur[37] ); uiSum += abs( piOrg[38] - piCur[38] ); uiSum += abs( piOrg[39] - piCur[39] ); uiSum += abs( piOrg[40] - piCur[40] ); uiSum += abs( piOrg[41] - piCur[41] ); uiSum += abs( piOrg[42] - piCur[42] ); uiSum += abs( piOrg[43] - piCur[43] ); uiSum += abs( piOrg[44] - piCur[44] ); uiSum += abs( piOrg[45] - piCur[45] ); uiSum += abs( piOrg[46] - piCur[46] ); uiSum += abs( piOrg[47] - piCur[47] ); piOrg += iStrideOrg; piCur += iStrideCur; } #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) } #endif uiSum <<= iSubShift; return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } // -------------------------------------------------------------------------------------------------------------------- // SSE // -------------------------------------------------------------------------------------------------------------------- Distortion TComRdCost::xGetSSE( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iCols = pcDtParam->iCols; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { iTemp = piOrg[n ] - piCur[n ]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); } piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE4( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { assert( pcDtParam->iCols == 4 ); return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { iTemp = piOrg[0] - piCur[0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[1] - piCur[1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[2] - piCur[2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[3] - piCur[3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE8( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { assert( pcDtParam->iCols == 8 ); return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { iTemp = piOrg[0] - piCur[0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[1] - piCur[1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[2] - piCur[2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[3] - piCur[3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[4] - piCur[4]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[5] - piCur[5]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[6] - piCur[6]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[7] - piCur[7]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE16( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { assert( pcDtParam->iCols == 16 ); return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { iTemp = piOrg[ 0] - piCur[ 0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 1] - piCur[ 1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 2] - piCur[ 2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 3] - piCur[ 3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 4] - piCur[ 4]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 5] - piCur[ 5]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 6] - piCur[ 6]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 7] - piCur[ 7]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 8] - piCur[ 8]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 9] - piCur[ 9]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[10] - piCur[10]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[11] - piCur[11]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[12] - piCur[12]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[13] - piCur[13]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[14] - piCur[14]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[15] - piCur[15]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE16N( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iCols = pcDtParam->iCols; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n+=16 ) { iTemp = piOrg[n+ 0] - piCur[n+ 0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 1] - piCur[n+ 1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 2] - piCur[n+ 2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 3] - piCur[n+ 3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 4] - piCur[n+ 4]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 5] - piCur[n+ 5]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 6] - piCur[n+ 6]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 7] - piCur[n+ 7]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 8] - piCur[n+ 8]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+ 9] - piCur[n+ 9]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+10] - piCur[n+10]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+11] - piCur[n+11]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+12] - piCur[n+12]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+13] - piCur[n+13]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+14] - piCur[n+14]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[n+15] - piCur[n+15]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); } piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE32( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { assert( pcDtParam->iCols == 32 ); return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { iTemp = piOrg[ 0] - piCur[ 0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 1] - piCur[ 1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 2] - piCur[ 2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 3] - piCur[ 3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 4] - piCur[ 4]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 5] - piCur[ 5]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 6] - piCur[ 6]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 7] - piCur[ 7]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 8] - piCur[ 8]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 9] - piCur[ 9]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[10] - piCur[10]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[11] - piCur[11]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[12] - piCur[12]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[13] - piCur[13]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[14] - piCur[14]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[15] - piCur[15]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[16] - piCur[16]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[17] - piCur[17]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[18] - piCur[18]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[19] - piCur[19]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[20] - piCur[20]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[21] - piCur[21]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[22] - piCur[22]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[23] - piCur[23]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[24] - piCur[24]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[25] - piCur[25]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[26] - piCur[26]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[27] - piCur[27]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[28] - piCur[28]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[29] - piCur[29]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[30] - piCur[30]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[31] - piCur[31]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } Distortion TComRdCost::xGetSSE64( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { assert( pcDtParam->iCols == 64 ); return TComRdCostWeightPrediction::xGetSSEw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; Int iRows = pcDtParam->iRows; Int iStrideOrg = pcDtParam->iStrideOrg; Int iStrideCur = pcDtParam->iStrideCur; Distortion uiSum = 0; UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Intermediate_Int iTemp; for( ; iRows != 0; iRows-- ) { iTemp = piOrg[ 0] - piCur[ 0]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 1] - piCur[ 1]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 2] - piCur[ 2]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 3] - piCur[ 3]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 4] - piCur[ 4]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 5] - piCur[ 5]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 6] - piCur[ 6]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 7] - piCur[ 7]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 8] - piCur[ 8]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[ 9] - piCur[ 9]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[10] - piCur[10]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[11] - piCur[11]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[12] - piCur[12]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[13] - piCur[13]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[14] - piCur[14]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[15] - piCur[15]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[16] - piCur[16]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[17] - piCur[17]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[18] - piCur[18]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[19] - piCur[19]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[20] - piCur[20]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[21] - piCur[21]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[22] - piCur[22]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[23] - piCur[23]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[24] - piCur[24]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[25] - piCur[25]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[26] - piCur[26]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[27] - piCur[27]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[28] - piCur[28]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[29] - piCur[29]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[30] - piCur[30]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[31] - piCur[31]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[32] - piCur[32]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[33] - piCur[33]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[34] - piCur[34]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[35] - piCur[35]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[36] - piCur[36]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[37] - piCur[37]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[38] - piCur[38]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[39] - piCur[39]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[40] - piCur[40]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[41] - piCur[41]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[42] - piCur[42]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[43] - piCur[43]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[44] - piCur[44]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[45] - piCur[45]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[46] - piCur[46]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[47] - piCur[47]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[48] - piCur[48]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[49] - piCur[49]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[50] - piCur[50]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[51] - piCur[51]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[52] - piCur[52]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[53] - piCur[53]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[54] - piCur[54]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[55] - piCur[55]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[56] - piCur[56]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[57] - piCur[57]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[58] - piCur[58]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[59] - piCur[59]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[60] - piCur[60]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[61] - piCur[61]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[62] - piCur[62]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); iTemp = piOrg[63] - piCur[63]; uiSum += Distortion(( iTemp * iTemp ) >> uiShift); piOrg += iStrideOrg; piCur += iStrideCur; } return ( uiSum ); } // -------------------------------------------------------------------------------------------------------------------- // HADAMARD with step (used in fractional search) // -------------------------------------------------------------------------------------------------------------------- Distortion TComRdCost::xCalcHADs2x2( const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep ) { Distortion satd = 0; TCoeff diff[4], m[4]; assert( iStep == 1 ); diff[0] = piOrg[0 ] - piCur[0]; diff[1] = piOrg[1 ] - piCur[1]; diff[2] = piOrg[iStrideOrg ] - piCur[0 + iStrideCur]; diff[3] = piOrg[iStrideOrg + 1] - piCur[1 + iStrideCur]; m[0] = diff[0] + diff[2]; m[1] = diff[1] + diff[3]; m[2] = diff[0] - diff[2]; m[3] = diff[1] - diff[3]; satd += abs(m[0] + m[1]); satd += abs(m[0] - m[1]); satd += abs(m[2] + m[3]); satd += abs(m[2] - m[3]); return satd; } Distortion TComRdCost::xCalcHADs4x4( const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep ) { Int k; Distortion satd = 0; TCoeff diff[16], m[16], d[16]; assert( iStep == 1 ); for( k = 0; k < 16; k+=4 ) { diff[k+0] = piOrg[0] - piCur[0]; diff[k+1] = piOrg[1] - piCur[1]; diff[k+2] = piOrg[2] - piCur[2]; diff[k+3] = piOrg[3] - piCur[3]; piCur += iStrideCur; piOrg += iStrideOrg; } /*===== hadamard transform =====*/ m[ 0] = diff[ 0] + diff[12]; m[ 1] = diff[ 1] + diff[13]; m[ 2] = diff[ 2] + diff[14]; m[ 3] = diff[ 3] + diff[15]; m[ 4] = diff[ 4] + diff[ 8]; m[ 5] = diff[ 5] + diff[ 9]; m[ 6] = diff[ 6] + diff[10]; m[ 7] = diff[ 7] + diff[11]; m[ 8] = diff[ 4] - diff[ 8]; m[ 9] = diff[ 5] - diff[ 9]; m[10] = diff[ 6] - diff[10]; m[11] = diff[ 7] - diff[11]; m[12] = diff[ 0] - diff[12]; m[13] = diff[ 1] - diff[13]; m[14] = diff[ 2] - diff[14]; m[15] = diff[ 3] - diff[15]; d[ 0] = m[ 0] + m[ 4]; d[ 1] = m[ 1] + m[ 5]; d[ 2] = m[ 2] + m[ 6]; d[ 3] = m[ 3] + m[ 7]; d[ 4] = m[ 8] + m[12]; d[ 5] = m[ 9] + m[13]; d[ 6] = m[10] + m[14]; d[ 7] = m[11] + m[15]; d[ 8] = m[ 0] - m[ 4]; d[ 9] = m[ 1] - m[ 5]; d[10] = m[ 2] - m[ 6]; d[11] = m[ 3] - m[ 7]; d[12] = m[12] - m[ 8]; d[13] = m[13] - m[ 9]; d[14] = m[14] - m[10]; d[15] = m[15] - m[11]; m[ 0] = d[ 0] + d[ 3]; m[ 1] = d[ 1] + d[ 2]; m[ 2] = d[ 1] - d[ 2]; m[ 3] = d[ 0] - d[ 3]; m[ 4] = d[ 4] + d[ 7]; m[ 5] = d[ 5] + d[ 6]; m[ 6] = d[ 5] - d[ 6]; m[ 7] = d[ 4] - d[ 7]; m[ 8] = d[ 8] + d[11]; m[ 9] = d[ 9] + d[10]; m[10] = d[ 9] - d[10]; m[11] = d[ 8] - d[11]; m[12] = d[12] + d[15]; m[13] = d[13] + d[14]; m[14] = d[13] - d[14]; m[15] = d[12] - d[15]; d[ 0] = m[ 0] + m[ 1]; d[ 1] = m[ 0] - m[ 1]; d[ 2] = m[ 2] + m[ 3]; d[ 3] = m[ 3] - m[ 2]; d[ 4] = m[ 4] + m[ 5]; d[ 5] = m[ 4] - m[ 5]; d[ 6] = m[ 6] + m[ 7]; d[ 7] = m[ 7] - m[ 6]; d[ 8] = m[ 8] + m[ 9]; d[ 9] = m[ 8] - m[ 9]; d[10] = m[10] + m[11]; d[11] = m[11] - m[10]; d[12] = m[12] + m[13]; d[13] = m[12] - m[13]; d[14] = m[14] + m[15]; d[15] = m[15] - m[14]; for (k=0; k<16; ++k) { satd += abs(d[k]); } satd = ((satd+1)>>1); return satd; } Distortion TComRdCost::xCalcHADs8x8( const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) , Int bitDepth #endif ) { #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) if( bitDepth <= 10 ) { return( simdHADs8x8( piOrg , piCur , iStrideOrg , iStrideCur ) ); } #endif Int k, i, j, jj; Distortion sad = 0; TCoeff diff[64], m1[8][8], m2[8][8], m3[8][8]; assert( iStep == 1 ); for( k = 0; k < 64; k += 8 ) { diff[k+0] = piOrg[0] - piCur[0]; diff[k+1] = piOrg[1] - piCur[1]; diff[k+2] = piOrg[2] - piCur[2]; diff[k+3] = piOrg[3] - piCur[3]; diff[k+4] = piOrg[4] - piCur[4]; diff[k+5] = piOrg[5] - piCur[5]; diff[k+6] = piOrg[6] - piCur[6]; diff[k+7] = piOrg[7] - piCur[7]; piCur += iStrideCur; piOrg += iStrideOrg; } //horizontal for (j=0; j < 8; j++) { jj = j << 3; m2[j][0] = diff[jj ] + diff[jj+4]; m2[j][1] = diff[jj+1] + diff[jj+5]; m2[j][2] = diff[jj+2] + diff[jj+6]; m2[j][3] = diff[jj+3] + diff[jj+7]; m2[j][4] = diff[jj ] - diff[jj+4]; m2[j][5] = diff[jj+1] - diff[jj+5]; m2[j][6] = diff[jj+2] - diff[jj+6]; m2[j][7] = diff[jj+3] - diff[jj+7]; m1[j][0] = m2[j][0] + m2[j][2]; m1[j][1] = m2[j][1] + m2[j][3]; m1[j][2] = m2[j][0] - m2[j][2]; m1[j][3] = m2[j][1] - m2[j][3]; m1[j][4] = m2[j][4] + m2[j][6]; m1[j][5] = m2[j][5] + m2[j][7]; m1[j][6] = m2[j][4] - m2[j][6]; m1[j][7] = m2[j][5] - m2[j][7]; m2[j][0] = m1[j][0] + m1[j][1]; m2[j][1] = m1[j][0] - m1[j][1]; m2[j][2] = m1[j][2] + m1[j][3]; m2[j][3] = m1[j][2] - m1[j][3]; m2[j][4] = m1[j][4] + m1[j][5]; m2[j][5] = m1[j][4] - m1[j][5]; m2[j][6] = m1[j][6] + m1[j][7]; m2[j][7] = m1[j][6] - m1[j][7]; } //vertical for (i=0; i < 8; i++) { m3[0][i] = m2[0][i] + m2[4][i]; m3[1][i] = m2[1][i] + m2[5][i]; m3[2][i] = m2[2][i] + m2[6][i]; m3[3][i] = m2[3][i] + m2[7][i]; m3[4][i] = m2[0][i] - m2[4][i]; m3[5][i] = m2[1][i] - m2[5][i]; m3[6][i] = m2[2][i] - m2[6][i]; m3[7][i] = m2[3][i] - m2[7][i]; m1[0][i] = m3[0][i] + m3[2][i]; m1[1][i] = m3[1][i] + m3[3][i]; m1[2][i] = m3[0][i] - m3[2][i]; m1[3][i] = m3[1][i] - m3[3][i]; m1[4][i] = m3[4][i] + m3[6][i]; m1[5][i] = m3[5][i] + m3[7][i]; m1[6][i] = m3[4][i] - m3[6][i]; m1[7][i] = m3[5][i] - m3[7][i]; m2[0][i] = m1[0][i] + m1[1][i]; m2[1][i] = m1[0][i] - m1[1][i]; m2[2][i] = m1[2][i] + m1[3][i]; m2[3][i] = m1[2][i] - m1[3][i]; m2[4][i] = m1[4][i] + m1[5][i]; m2[5][i] = m1[4][i] - m1[5][i]; m2[6][i] = m1[6][i] + m1[7][i]; m2[7][i] = m1[6][i] - m1[7][i]; } for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { sad += abs(m2[i][j]); } } sad=((sad+2)>>2); return sad; } Distortion TComRdCost::xGetHADs( DistParam* pcDtParam ) { if ( pcDtParam->bApplyWeight ) { return TComRdCostWeightPrediction::xGetHADsw( pcDtParam ); } const Pel* piOrg = pcDtParam->pOrg; const Pel* piCur = pcDtParam->pCur; const Int iRows = pcDtParam->iRows; const Int iCols = pcDtParam->iCols; const Int iStrideCur = pcDtParam->iStrideCur; const Int iStrideOrg = pcDtParam->iStrideOrg; const Int iStep = pcDtParam->iStep; Int x, y; Distortion uiSum = 0; if( ( iRows % 8 == 0) && (iCols % 8 == 0) ) { Int iOffsetOrg = iStrideOrg<<3; Int iOffsetCur = iStrideCur<<3; for ( y=0; ybitDepth #endif ); } piOrg += iOffsetOrg; piCur += iOffsetCur; } } else if( ( iRows % 4 == 0) && (iCols % 4 == 0) ) { Int iOffsetOrg = iStrideOrg<<2; Int iOffsetCur = iStrideCur<<2; for ( y=0; y> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComRdCost.h000066400000000000000000000223411442026013100204060ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRdCost.h \brief RD cost computation classes (header) */ #ifndef __TCOMRDCOST__ #define __TCOMRDCOST__ #include "CommonDef.h" #include "TComPattern.h" #include "TComMv.h" #include "TComSlice.h" #include "TComRdCostWeightPrediction.h" //! \ingroup TLibCommon //! \{ class DistParam; class TComPattern; // ==================================================================================================================== // Type definition // ==================================================================================================================== // for function pointer typedef Distortion (*FpDistFunc) (DistParam*); // TODO: can this pointer be replaced with a reference? - there are no NULL checks on pointer. // ==================================================================================================================== // Class definition // ==================================================================================================================== /// distortion parameter class class DistParam { public: const Pel* pOrg; const Pel* pCur; Int iStrideOrg; Int iStrideCur; Int iRows; Int iCols; Int iStep; FpDistFunc DistFunc; Int bitDepth; Bool bApplyWeight; // whether weighted prediction is used or not Bool bIsBiPred; const WPScalingParam *wpCur; // weighted prediction scaling parameters for current ref ComponentID compIdx; Distortion m_maximumDistortionForEarlyExit; /// During cost calculations, if distortion exceeds this value, cost calculations may early-terminate. // (vertical) subsampling shift (for reducing complexity) // - 0 = no subsampling, 1 = even rows, 2 = every 4th, etc. Int iSubShift; DistParam() : pOrg(NULL), pCur(NULL), iStrideOrg(0), iStrideCur(0), iRows(0), iCols(0), iStep(1), DistFunc(NULL), bitDepth(0), bApplyWeight(false), bIsBiPred(false), wpCur(NULL), compIdx(MAX_NUM_COMPONENT), m_maximumDistortionForEarlyExit(std::numeric_limits::max()), iSubShift(0) { } }; /// RD cost computation class class TComRdCost { private: // for distortion FpDistFunc m_afpDistortFunc[DF_TOTAL_FUNCTIONS]; // [eDFunc] CostMode m_costMode; Double m_distortionWeight[MAX_NUM_COMPONENT]; // only chroma values are used. Double m_dLambda; Double m_sqrtLambda; Double m_dLambdaMotionSAD[2 /* 0=standard, 1=for transquant bypass when mixed-lossless cost evaluation enabled*/]; Double m_dLambdaMotionSSE[2 /* 0=standard, 1=for transquant bypass when mixed-lossless cost evaluation enabled*/]; Double m_dFrameLambda; // for motion cost TComMv m_mvPredictor; Double m_motionLambda; Int m_iCostScale; public: TComRdCost(); virtual ~TComRdCost(); Double calcRdCost( Double numBits, Distortion distortion, DFunc eDFunc = DF_DEFAULT ); Void setDistortionWeight ( const ComponentID compID, const Double distortionWeight ) { m_distortionWeight[compID] = distortionWeight; } Void setLambda ( Double dLambda, const BitDepths &bitDepths ); Void setFrameLambda ( Double dLambda ) { m_dFrameLambda = dLambda; } Double getSqrtLambda () { return m_sqrtLambda; } Double getLambda() { return m_dLambda; } Double getChromaWeight () { return ((m_distortionWeight[COMPONENT_Cb] + m_distortionWeight[COMPONENT_Cr]) / 2.0); } Void setCostMode(CostMode m ) { m_costMode = m; } // Distortion Functions Void init(); Void setDistParam( UInt uiBlkWidth, UInt uiBlkHeight, DFunc eDFunc, DistParam& rcDistParam ); Void setDistParam( const TComPattern* const pcPatternKey, const Pel* piRefY, Int iRefStride, DistParam& rcDistParam ); Void setDistParam( const TComPattern* const pcPatternKey, const Pel* piRefY, Int iRefStride, Int iStep, DistParam& rcDistParam, Bool bHADME=false ); Void setDistParam( DistParam& rcDP, Int bitDepth, const Pel* p1, Int iStride1, const Pel* p2, Int iStride2, Int iWidth, Int iHeight, Bool bHadamard = false ); Distortion calcHAD(Int bitDepth, const Pel* pi0, Int iStride0, const Pel* pi1, Int iStride1, Int iWidth, Int iHeight ); // for motion cost static UInt xGetExpGolombNumberOfBits( Int iVal ); Void selectMotionLambda( Bool bSad, Int iAdd, Bool bIsTransquantBypass ) { m_motionLambda = (bSad ? m_dLambdaMotionSAD[(bIsTransquantBypass && m_costMode==COST_MIXED_LOSSLESS_LOSSY_CODING) ?1:0] + iAdd : m_dLambdaMotionSSE[(bIsTransquantBypass && m_costMode==COST_MIXED_LOSSLESS_LOSSY_CODING)?1:0] + iAdd); } Void setPredictor( TComMv& rcMv ) { m_mvPredictor = rcMv; } Void setCostScale( Int iCostScale ) { m_iCostScale = iCostScale; } Distortion getCost( UInt b ) { return Distortion(( m_motionLambda * b ) / 65536.0); } Distortion getCostOfVectorWithPredictor( const Int x, const Int y ) { return Distortion((m_motionLambda * getBitsOfVectorWithPredictor(x, y)) / 65536.0); } UInt getBitsOfVectorWithPredictor( const Int x, const Int y ) { return xGetExpGolombNumberOfBits((x << m_iCostScale) - m_mvPredictor.getHor()) + xGetExpGolombNumberOfBits((y << m_iCostScale) - m_mvPredictor.getVer()); } private: static Distortion xGetSSE ( DistParam* pcDtParam ); static Distortion xGetSSE4 ( DistParam* pcDtParam ); static Distortion xGetSSE8 ( DistParam* pcDtParam ); static Distortion xGetSSE16 ( DistParam* pcDtParam ); static Distortion xGetSSE32 ( DistParam* pcDtParam ); static Distortion xGetSSE64 ( DistParam* pcDtParam ); static Distortion xGetSSE16N ( DistParam* pcDtParam ); static Distortion xGetSAD ( DistParam* pcDtParam ); static Distortion xGetSAD4 ( DistParam* pcDtParam ); static Distortion xGetSAD8 ( DistParam* pcDtParam ); static Distortion xGetSAD16 ( DistParam* pcDtParam ); static Distortion xGetSAD32 ( DistParam* pcDtParam ); static Distortion xGetSAD64 ( DistParam* pcDtParam ); static Distortion xGetSAD16N ( DistParam* pcDtParam ); static Distortion xGetSAD12 ( DistParam* pcDtParam ); static Distortion xGetSAD24 ( DistParam* pcDtParam ); static Distortion xGetSAD48 ( DistParam* pcDtParam ); static Distortion xGetHADs ( DistParam* pcDtParam ); static Distortion xCalcHADs2x2 ( const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep ); static Distortion xCalcHADs4x4 ( const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep ); static Distortion xCalcHADs8x8 ( const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep #if VECTOR_CODING__DISTORTION_CALCULATIONS && (RExt__HIGH_BIT_DEPTH_SUPPORT==0) , Int bitDepth #endif ); public: Distortion getDistPart(Int bitDepth, const Pel* piCur, Int iCurStride, const Pel* piOrg, Int iOrgStride, UInt uiBlkWidth, UInt uiBlkHeight, const ComponentID compID, DFunc eDFunc = DF_SSE ); };// END CLASS DEFINITION TComRdCost //! \} #endif // __TCOMRDCOST__ HM-HM-18.0/source/Lib/TLibCommon/TComRdCostWeightPrediction.cpp000066400000000000000000000456751442026013100241510ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRdCostWeightPrediction.cpp \brief RD cost computation class with Weighted-Prediction */ #include #include #include "TComRdCost.h" #include "TComRdCostWeightPrediction.h" static Distortion xCalcHADs2x2w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep ); static Distortion xCalcHADs4x4w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep ); static Distortion xCalcHADs8x8w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCurr, Int iStrideOrg, Int iStrideCur, Int iStep ); // -------------------------------------------------------------------------------------------------------------------- // SAD // -------------------------------------------------------------------------------------------------------------------- /** get weighted SAD cost * \param pcDtParam * \returns Distortion */ Distortion TComRdCostWeightPrediction::xGetSADw( DistParam* pcDtParam ) { const Pel *piOrg = pcDtParam->pOrg; const Pel *piCur = pcDtParam->pCur; const Int iCols = pcDtParam->iCols; const Int iStrideCur = pcDtParam->iStrideCur; const Int iStrideOrg = pcDtParam->iStrideOrg; const ComponentID compID = pcDtParam->compIdx; assert(compIDwpCur[compID]; const Int w0 = wpCur.w; const Int offset = wpCur.offset; const Int shift = wpCur.shift; const Int round = wpCur.round; const Int distortionShift = DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8); Distortion uiSum = 0; // Default weight if (w0 == 1 << shift) { // no offset if (offset == 0) { for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { uiSum += abs( piOrg[n] - piCur[n] ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } else { // Lets not clip for the bipredictive case since clipping should be done after // combining both elements. Unfortunately the code uses the suboptimal "subtraction" // method, which is faster but introduces the clipping issue (therefore Bipred is suboptimal). if (pcDtParam->bIsBiPred) { for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { uiSum += abs( piOrg[n] - (piCur[n] + offset) ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } else { const Pel iMaxValue = (Pel) ((1 << pcDtParam->bitDepth) - 1); for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = Clip3((Pel) 0, iMaxValue, (Pel) (piCur[n] + offset)) ; uiSum += abs( piOrg[n] - pred ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } } } else { // Lets not clip for the bipredictive case since clipping should be done after // combining both elements. Unfortunately the code uses the suboptimal "subtraction" // method, which is faster but introduces the clipping issue (therefore Bipred is suboptimal). if (pcDtParam->bIsBiPred) { for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = ( (w0*piCur[n] + round) >> shift ) + offset ; uiSum += abs( piOrg[n] - pred ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } else { const Pel iMaxValue = (Pel) ((1 << pcDtParam->bitDepth) - 1); if (offset == 0) { for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = Clip3((Pel) 0, iMaxValue, (Pel) (( (w0*piCur[n] + round) >> shift ))) ; uiSum += abs( piOrg[n] - pred ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } else { for(Int iRows = pcDtParam->iRows; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = Clip3((Pel) 0, iMaxValue, (Pel) (( (w0*piCur[n] + round) >> shift ) + offset)) ; uiSum += abs( piOrg[n] - pred ); } if (pcDtParam->m_maximumDistortionForEarlyExit < ( uiSum >> distortionShift)) { return uiSum >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } } } //pcDtParam->compIdx = MAX_NUM_COMPONENT; // reset for DEBUG (assert test) return uiSum >> distortionShift; } // -------------------------------------------------------------------------------------------------------------------- // SSE // -------------------------------------------------------------------------------------------------------------------- /** get weighted SSD cost * \param pcDtParam * \returns Distortion */ Distortion TComRdCostWeightPrediction::xGetSSEw( DistParam* pcDtParam ) { const Pel *piOrg = pcDtParam->pOrg; const Pel *piCur = pcDtParam->pCur; const Int iCols = pcDtParam->iCols; const Int iStrideOrg = pcDtParam->iStrideOrg; const Int iStrideCur = pcDtParam->iStrideCur; const ComponentID compIdx = pcDtParam->compIdx; assert( pcDtParam->iSubShift == 0 ); // NOTE: what is this protecting? assert(compIdxwpCur[compIdx]; const Int w0 = wpCur.w; const Int offset = wpCur.offset; const Int shift = wpCur.shift; const Int round = wpCur.round; const UInt distortionShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1); Distortion sum = 0; if (pcDtParam->bIsBiPred) { for(Int iRows = pcDtParam->iRows ; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = ( (w0*piCur[n] + round) >> shift ) + offset ; const Pel residual = piOrg[n] - pred; sum += ( Distortion(residual) * Distortion(residual) ) >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } else { const Pel iMaxValue = (Pel) ((1 << pcDtParam->bitDepth) - 1); for(Int iRows = pcDtParam->iRows ; iRows != 0; iRows-- ) { for (Int n = 0; n < iCols; n++ ) { const Pel pred = Clip3((Pel) 0, iMaxValue, (Pel) (( (w0*piCur[n] + round) >> shift ) + offset)) ; const Pel residual = piOrg[n] - pred; sum += ( Distortion(residual) * Distortion(residual) ) >> distortionShift; } piOrg += iStrideOrg; piCur += iStrideCur; } } //pcDtParam->compIdx = MAX_NUM_COMPONENT; // reset for DEBUG (assert test) return sum; } // -------------------------------------------------------------------------------------------------------------------- // HADAMARD with step (used in fractional search) // -------------------------------------------------------------------------------------------------------------------- //! get weighted Hadamard cost for 2x2 block Distortion xCalcHADs2x2w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep ) { const Int round = wpCur.round; const Int shift = wpCur.shift; const Int offset = wpCur.offset; const Int w0 = wpCur.w; Distortion satd = 0; TCoeff diff[4]; TCoeff m[4]; Pel pred; pred = ( (w0*piCur[0*iStep ] + round) >> shift ) + offset ; diff[0] = piOrg[0 ] - pred; pred = ( (w0*piCur[1*iStep ] + round) >> shift ) + offset ; diff[1] = piOrg[1 ] - pred; pred = ( (w0*piCur[0*iStep + iStrideCur] + round) >> shift ) + offset ; diff[2] = piOrg[iStrideOrg ] - pred; pred = ( (w0*piCur[1*iStep + iStrideCur] + round) >> shift ) + offset ; diff[3] = piOrg[iStrideOrg + 1] - pred; m[0] = diff[0] + diff[2]; m[1] = diff[1] + diff[3]; m[2] = diff[0] - diff[2]; m[3] = diff[1] - diff[3]; satd += abs(m[0] + m[1]); satd += abs(m[0] - m[1]); satd += abs(m[2] + m[3]); satd += abs(m[2] - m[3]); return satd; } //! get weighted Hadamard cost for 4x4 block Distortion xCalcHADs4x4w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep ) { const Int round = wpCur.round; const Int shift = wpCur.shift; const Int offset = wpCur.offset; const Int w0 = wpCur.w; Distortion satd = 0; TCoeff diff[16]; TCoeff m[16]; TCoeff d[16]; for(Int k = 0; k < 16; k+=4 ) { Pel pred; pred = ( (w0*piCur[0*iStep] + round) >> shift ) + offset ; diff[k+0] = piOrg[0] - pred; pred = ( (w0*piCur[1*iStep] + round) >> shift ) + offset ; diff[k+1] = piOrg[1] - pred; pred = ( (w0*piCur[2*iStep] + round) >> shift ) + offset ; diff[k+2] = piOrg[2] - pred; pred = ( (w0*piCur[3*iStep] + round) >> shift ) + offset ; diff[k+3] = piOrg[3] - pred; piCur += iStrideCur; piOrg += iStrideOrg; } /*===== hadamard transform =====*/ m[ 0] = diff[ 0] + diff[12]; m[ 1] = diff[ 1] + diff[13]; m[ 2] = diff[ 2] + diff[14]; m[ 3] = diff[ 3] + diff[15]; m[ 4] = diff[ 4] + diff[ 8]; m[ 5] = diff[ 5] + diff[ 9]; m[ 6] = diff[ 6] + diff[10]; m[ 7] = diff[ 7] + diff[11]; m[ 8] = diff[ 4] - diff[ 8]; m[ 9] = diff[ 5] - diff[ 9]; m[10] = diff[ 6] - diff[10]; m[11] = diff[ 7] - diff[11]; m[12] = diff[ 0] - diff[12]; m[13] = diff[ 1] - diff[13]; m[14] = diff[ 2] - diff[14]; m[15] = diff[ 3] - diff[15]; d[ 0] = m[ 0] + m[ 4]; d[ 1] = m[ 1] + m[ 5]; d[ 2] = m[ 2] + m[ 6]; d[ 3] = m[ 3] + m[ 7]; d[ 4] = m[ 8] + m[12]; d[ 5] = m[ 9] + m[13]; d[ 6] = m[10] + m[14]; d[ 7] = m[11] + m[15]; d[ 8] = m[ 0] - m[ 4]; d[ 9] = m[ 1] - m[ 5]; d[10] = m[ 2] - m[ 6]; d[11] = m[ 3] - m[ 7]; d[12] = m[12] - m[ 8]; d[13] = m[13] - m[ 9]; d[14] = m[14] - m[10]; d[15] = m[15] - m[11]; m[ 0] = d[ 0] + d[ 3]; m[ 1] = d[ 1] + d[ 2]; m[ 2] = d[ 1] - d[ 2]; m[ 3] = d[ 0] - d[ 3]; m[ 4] = d[ 4] + d[ 7]; m[ 5] = d[ 5] + d[ 6]; m[ 6] = d[ 5] - d[ 6]; m[ 7] = d[ 4] - d[ 7]; m[ 8] = d[ 8] + d[11]; m[ 9] = d[ 9] + d[10]; m[10] = d[ 9] - d[10]; m[11] = d[ 8] - d[11]; m[12] = d[12] + d[15]; m[13] = d[13] + d[14]; m[14] = d[13] - d[14]; m[15] = d[12] - d[15]; d[ 0] = m[ 0] + m[ 1]; d[ 1] = m[ 0] - m[ 1]; d[ 2] = m[ 2] + m[ 3]; d[ 3] = m[ 3] - m[ 2]; d[ 4] = m[ 4] + m[ 5]; d[ 5] = m[ 4] - m[ 5]; d[ 6] = m[ 6] + m[ 7]; d[ 7] = m[ 7] - m[ 6]; d[ 8] = m[ 8] + m[ 9]; d[ 9] = m[ 8] - m[ 9]; d[10] = m[10] + m[11]; d[11] = m[11] - m[10]; d[12] = m[12] + m[13]; d[13] = m[12] - m[13]; d[14] = m[14] + m[15]; d[15] = m[15] - m[14]; for (Int k=0; k<16; ++k) { satd += abs(d[k]); } satd = ((satd+1)>>1); return satd; } //! get weighted Hadamard cost for 8x8 block Distortion xCalcHADs8x8w( const WPScalingParam &wpCur, const Pel *piOrg, const Pel *piCur, Int iStrideOrg, Int iStrideCur, Int iStep ) { Distortion sad=0; TCoeff diff[64], m1[8][8], m2[8][8], m3[8][8]; Int iStep2 = iStep<<1; Int iStep3 = iStep2 + iStep; Int iStep4 = iStep3 + iStep; Int iStep5 = iStep4 + iStep; Int iStep6 = iStep5 + iStep; Int iStep7 = iStep6 + iStep; const Int round = wpCur.round; const Int shift = wpCur.shift; const Int offset = wpCur.offset; const Int w0 = wpCur.w; Pel pred; for(Int k = 0; k < 64; k+=8 ) { pred = ( (w0*piCur[ 0] + round) >> shift ) + offset ; diff[k+0] = piOrg[0] - pred; pred = ( (w0*piCur[iStep ] + round) >> shift ) + offset ; diff[k+1] = piOrg[1] - pred; pred = ( (w0*piCur[iStep2] + round) >> shift ) + offset ; diff[k+2] = piOrg[2] - pred; pred = ( (w0*piCur[iStep3] + round) >> shift ) + offset ; diff[k+3] = piOrg[3] - pred; pred = ( (w0*piCur[iStep4] + round) >> shift ) + offset ; diff[k+4] = piOrg[4] - pred; pred = ( (w0*piCur[iStep5] + round) >> shift ) + offset ; diff[k+5] = piOrg[5] - pred; pred = ( (w0*piCur[iStep6] + round) >> shift ) + offset ; diff[k+6] = piOrg[6] - pred; pred = ( (w0*piCur[iStep7] + round) >> shift ) + offset ; diff[k+7] = piOrg[7] - pred; piCur += iStrideCur; piOrg += iStrideOrg; } //horizontal for (Int j=0; j < 8; j++) { const Int jj = j << 3; m2[j][0] = diff[jj ] + diff[jj+4]; m2[j][1] = diff[jj+1] + diff[jj+5]; m2[j][2] = diff[jj+2] + diff[jj+6]; m2[j][3] = diff[jj+3] + diff[jj+7]; m2[j][4] = diff[jj ] - diff[jj+4]; m2[j][5] = diff[jj+1] - diff[jj+5]; m2[j][6] = diff[jj+2] - diff[jj+6]; m2[j][7] = diff[jj+3] - diff[jj+7]; m1[j][0] = m2[j][0] + m2[j][2]; m1[j][1] = m2[j][1] + m2[j][3]; m1[j][2] = m2[j][0] - m2[j][2]; m1[j][3] = m2[j][1] - m2[j][3]; m1[j][4] = m2[j][4] + m2[j][6]; m1[j][5] = m2[j][5] + m2[j][7]; m1[j][6] = m2[j][4] - m2[j][6]; m1[j][7] = m2[j][5] - m2[j][7]; m2[j][0] = m1[j][0] + m1[j][1]; m2[j][1] = m1[j][0] - m1[j][1]; m2[j][2] = m1[j][2] + m1[j][3]; m2[j][3] = m1[j][2] - m1[j][3]; m2[j][4] = m1[j][4] + m1[j][5]; m2[j][5] = m1[j][4] - m1[j][5]; m2[j][6] = m1[j][6] + m1[j][7]; m2[j][7] = m1[j][6] - m1[j][7]; } //vertical for (Int i=0; i < 8; i++) { m3[0][i] = m2[0][i] + m2[4][i]; m3[1][i] = m2[1][i] + m2[5][i]; m3[2][i] = m2[2][i] + m2[6][i]; m3[3][i] = m2[3][i] + m2[7][i]; m3[4][i] = m2[0][i] - m2[4][i]; m3[5][i] = m2[1][i] - m2[5][i]; m3[6][i] = m2[2][i] - m2[6][i]; m3[7][i] = m2[3][i] - m2[7][i]; m1[0][i] = m3[0][i] + m3[2][i]; m1[1][i] = m3[1][i] + m3[3][i]; m1[2][i] = m3[0][i] - m3[2][i]; m1[3][i] = m3[1][i] - m3[3][i]; m1[4][i] = m3[4][i] + m3[6][i]; m1[5][i] = m3[5][i] + m3[7][i]; m1[6][i] = m3[4][i] - m3[6][i]; m1[7][i] = m3[5][i] - m3[7][i]; m2[0][i] = m1[0][i] + m1[1][i]; m2[1][i] = m1[0][i] - m1[1][i]; m2[2][i] = m1[2][i] + m1[3][i]; m2[3][i] = m1[2][i] - m1[3][i]; m2[4][i] = m1[4][i] + m1[5][i]; m2[5][i] = m1[4][i] - m1[5][i]; m2[6][i] = m1[6][i] + m1[7][i]; m2[7][i] = m1[6][i] - m1[7][i]; } for (Int j=0; j < 8; j++) { for (Int i=0; i < 8; i++) { sad += (abs(m2[j][i])); } } sad=((sad+2)>>2); return sad; } //! get weighted Hadamard cost Distortion TComRdCostWeightPrediction::xGetHADsw( DistParam* pcDtParam ) { const Pel *piOrg = pcDtParam->pOrg; const Pel *piCur = pcDtParam->pCur; const Int iRows = pcDtParam->iRows; const Int iCols = pcDtParam->iCols; const Int iStrideCur = pcDtParam->iStrideCur; const Int iStrideOrg = pcDtParam->iStrideOrg; const Int iStep = pcDtParam->iStep; const ComponentID compIdx = pcDtParam->compIdx; assert(compIdxwpCur[compIdx]; Distortion uiSum = 0; if( ( iRows % 8 == 0) && (iCols % 8 == 0) ) { const Int iOffsetOrg = iStrideOrg<<3; const Int iOffsetCur = iStrideCur<<3; for (Int y=0; y> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8); } HM-HM-18.0/source/Lib/TLibCommon/TComRdCostWeightPrediction.h000066400000000000000000000051721442026013100236020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRdCostWeightPrediction.h \brief RD cost computation namespace (header) */ #ifndef __TCOMRDCOSTWEIGHTPREDICTION__ #define __TCOMRDCOSTWEIGHTPREDICTION__ #include "CommonDef.h" class DistParam; class TComPattern; // ==================================================================================================================== // Namespace definition // ==================================================================================================================== /// RD cost computation namespace, with Weighted Prediction namespace TComRdCostWeightPrediction { Distortion xGetSSEw ( DistParam* pcDtParam ); Distortion xGetSADw ( DistParam* pcDtParam ); Distortion xGetHADsw( DistParam* pcDtParam ); }// END NAMESPACE DEFINITION TComRdCostWeightPrediction #endif // __TCOMRDCOSTWEIGHTPREDICTION__ HM-HM-18.0/source/Lib/TLibCommon/TComRectangle.h000066400000000000000000000036711442026013100211210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __TCOMRECTANGLE__ #define __TCOMRECTANGLE__ struct TComRectangle { UInt width; UInt height; UInt x0; UInt y0; }; #endif HM-HM-18.0/source/Lib/TLibCommon/TComRom.cpp000066400000000000000000001444171442026013100203110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRom.cpp \brief global variables & functions */ #include "TComRom.h" #include #include #include #include #include #include "TComDataCU.h" #include "Debug.h" // ==================================================================================================================== // Initialize / destroy functions // ==================================================================================================================== //! \ingroup TLibCommon //! \{ const TChar* nalUnitTypeToString(NalUnitType type) { switch (type) { case NAL_UNIT_CODED_SLICE_TRAIL_R: return "TRAIL_R"; case NAL_UNIT_CODED_SLICE_TRAIL_N: return "TRAIL_N"; case NAL_UNIT_CODED_SLICE_TSA_R: return "TSA_R"; case NAL_UNIT_CODED_SLICE_TSA_N: return "TSA_N"; case NAL_UNIT_CODED_SLICE_STSA_R: return "STSA_R"; case NAL_UNIT_CODED_SLICE_STSA_N: return "STSA_N"; case NAL_UNIT_CODED_SLICE_BLA_W_LP: return "BLA_W_LP"; case NAL_UNIT_CODED_SLICE_BLA_W_RADL: return "BLA_W_RADL"; case NAL_UNIT_CODED_SLICE_BLA_N_LP: return "BLA_N_LP"; case NAL_UNIT_CODED_SLICE_IDR_W_RADL: return "IDR_W_RADL"; case NAL_UNIT_CODED_SLICE_IDR_N_LP: return "IDR_N_LP"; case NAL_UNIT_CODED_SLICE_CRA: return "CRA"; case NAL_UNIT_CODED_SLICE_RADL_R: return "RADL_R"; case NAL_UNIT_CODED_SLICE_RADL_N: return "RADL_N"; case NAL_UNIT_CODED_SLICE_RASL_R: return "RASL_R"; case NAL_UNIT_CODED_SLICE_RASL_N: return "RASL_N"; case NAL_UNIT_VPS: return "VPS"; case NAL_UNIT_SPS: return "SPS"; case NAL_UNIT_PPS: return "PPS"; case NAL_UNIT_ACCESS_UNIT_DELIMITER: return "AUD"; case NAL_UNIT_EOS: return "EOS"; case NAL_UNIT_EOB: return "EOB"; case NAL_UNIT_FILLER_DATA: return "FILLER"; case NAL_UNIT_PREFIX_SEI: return "Prefix SEI"; case NAL_UNIT_SUFFIX_SEI: return "Suffix SEI"; default: return "UNK"; } } class ScanGenerator { private: UInt m_line, m_column; const UInt m_blockWidth, m_blockHeight; const UInt m_stride; const COEFF_SCAN_TYPE m_scanType; public: ScanGenerator(UInt blockWidth, UInt blockHeight, UInt stride, COEFF_SCAN_TYPE scanType) : m_line(0), m_column(0), m_blockWidth(blockWidth), m_blockHeight(blockHeight), m_stride(stride), m_scanType(scanType) { } UInt GetCurrentX() const { return m_column; } UInt GetCurrentY() const { return m_line; } UInt GetNextIndex(UInt blockOffsetX, UInt blockOffsetY) { Int rtn=((m_line + blockOffsetY) * m_stride) + m_column + blockOffsetX; //advance line and column to the next position switch (m_scanType) { //------------------------------------------------ case SCAN_DIAG: { if ((m_column == (m_blockWidth - 1)) || (m_line == 0)) //if we reach the end of a rank, go diagonally down to the next one { m_line += m_column + 1; m_column = 0; if (m_line >= m_blockHeight) //if that takes us outside the block, adjust so that we are back on the bottom row { m_column += m_line - (m_blockHeight - 1); m_line = m_blockHeight - 1; } } else { m_column++; m_line--; } } break; //------------------------------------------------ case SCAN_HOR: { if (m_column == (m_blockWidth - 1)) { m_line++; m_column = 0; } else { m_column++; } } break; //------------------------------------------------ case SCAN_VER: { if (m_line == (m_blockHeight - 1)) { m_column++; m_line = 0; } else { m_line++; } } break; //------------------------------------------------ default: { std::cerr << "ERROR: Unknown scan type \"" << m_scanType << "\"in ScanGenerator::GetNextIndex" << std::endl; exit(1); } break; } return rtn; } }; // initialize ROM variables Void initROM() { Int i, c; // g_aucConvertToBit[ x ]: log2(x/4), if x=4 -> 0, x=8 -> 1, x=16 -> 2, ... ::memset( g_aucConvertToBit, -1, sizeof( g_aucConvertToBit ) ); c=0; for ( i=4; i<=MAX_CU_SIZE; i*=2 ) { g_aucConvertToBit[ i ] = c; c++; } // initialise scan orders for(UInt log2BlockHeight = 0; log2BlockHeight < MAX_CU_DEPTH; log2BlockHeight++) { for(UInt log2BlockWidth = 0; log2BlockWidth < MAX_CU_DEPTH; log2BlockWidth++) { const UInt blockWidth = 1 << log2BlockWidth; const UInt blockHeight = 1 << log2BlockHeight; const UInt totalValues = blockWidth * blockHeight; //-------------------------------------------------------------------------------------------------- //non-grouped scan orders for (UInt scanTypeIndex = 0; scanTypeIndex < SCAN_NUMBER_OF_TYPES; scanTypeIndex++) { const COEFF_SCAN_TYPE scanType = COEFF_SCAN_TYPE(scanTypeIndex); g_scanOrder[SCAN_UNGROUPED][scanType][log2BlockWidth][log2BlockHeight] = new UInt[totalValues]; ScanGenerator fullBlockScan(blockWidth, blockHeight, blockWidth, scanType); for (UInt scanPosition = 0; scanPosition < totalValues; scanPosition++) { g_scanOrder[SCAN_UNGROUPED][scanType][log2BlockWidth][log2BlockHeight][scanPosition] = fullBlockScan.GetNextIndex(0, 0); } } //-------------------------------------------------------------------------------------------------- //grouped scan orders const UInt groupWidth = 1 << MLS_CG_LOG2_WIDTH; const UInt groupHeight = 1 << MLS_CG_LOG2_HEIGHT; const UInt widthInGroups = blockWidth >> MLS_CG_LOG2_WIDTH; const UInt heightInGroups = blockHeight >> MLS_CG_LOG2_HEIGHT; const UInt groupSize = groupWidth * groupHeight; const UInt totalGroups = widthInGroups * heightInGroups; for (UInt scanTypeIndex = 0; scanTypeIndex < SCAN_NUMBER_OF_TYPES; scanTypeIndex++) { const COEFF_SCAN_TYPE scanType = COEFF_SCAN_TYPE(scanTypeIndex); g_scanOrder[SCAN_GROUPED_4x4][scanType][log2BlockWidth][log2BlockHeight] = new UInt[totalValues]; ScanGenerator fullBlockScan(widthInGroups, heightInGroups, groupWidth, scanType); for (UInt groupIndex = 0; groupIndex < totalGroups; groupIndex++) { const UInt groupPositionY = fullBlockScan.GetCurrentY(); const UInt groupPositionX = fullBlockScan.GetCurrentX(); const UInt groupOffsetX = groupPositionX * groupWidth; const UInt groupOffsetY = groupPositionY * groupHeight; const UInt groupOffsetScan = groupIndex * groupSize; ScanGenerator groupScan(groupWidth, groupHeight, blockWidth, scanType); for (UInt scanPosition = 0; scanPosition < groupSize; scanPosition++) { g_scanOrder[SCAN_GROUPED_4x4][scanType][log2BlockWidth][log2BlockHeight][groupOffsetScan + scanPosition] = groupScan.GetNextIndex(groupOffsetX, groupOffsetY); } fullBlockScan.GetNextIndex(0,0); } } //-------------------------------------------------------------------------------------------------- } } } Void destroyROM() { for(UInt groupTypeIndex = 0; groupTypeIndex < SCAN_NUMBER_OF_GROUP_TYPES; groupTypeIndex++) { for (UInt scanOrderIndex = 0; scanOrderIndex < SCAN_NUMBER_OF_TYPES; scanOrderIndex++) { for (UInt log2BlockWidth = 0; log2BlockWidth < MAX_CU_DEPTH; log2BlockWidth++) { for (UInt log2BlockHeight = 0; log2BlockHeight < MAX_CU_DEPTH; log2BlockHeight++) { delete [] g_scanOrder[groupTypeIndex][scanOrderIndex][log2BlockWidth][log2BlockHeight]; } } } } } // ==================================================================================================================== // Data structure related table & variable // ==================================================================================================================== UInt g_auiZscanToRaster [ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ] = { 0, }; UInt g_auiRasterToZscan [ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ] = { 0, }; UInt g_auiRasterToPelX [ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ] = { 0, }; UInt g_auiRasterToPelY [ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ] = { 0, }; const UInt g_auiPUOffset[NUMBER_OF_PART_SIZES] = { 0, 8, 4, 4, 2, 10, 1, 5}; Void initZscanToRaster ( Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx ) { Int iStride = 1 << ( iMaxDepth - 1 ); if ( iDepth == iMaxDepth ) { rpuiCurrIdx[0] = uiStartVal; rpuiCurrIdx++; } else { Int iStep = iStride >> iDepth; initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal, rpuiCurrIdx ); initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep, rpuiCurrIdx ); initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride, rpuiCurrIdx ); initZscanToRaster( iMaxDepth, iDepth+1, uiStartVal+iStep*iStride+iStep, rpuiCurrIdx ); } } Void initRasterToZscan ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth ) { UInt uiMinCUWidth = uiMaxCUWidth >> ( uiMaxDepth - 1 ); UInt uiMinCUHeight = uiMaxCUHeight >> ( uiMaxDepth - 1 ); UInt uiNumPartInWidth = (UInt)uiMaxCUWidth / uiMinCUWidth; UInt uiNumPartInHeight = (UInt)uiMaxCUHeight / uiMinCUHeight; for ( UInt i = 0; i < uiNumPartInWidth*uiNumPartInHeight; i++ ) { g_auiRasterToZscan[ g_auiZscanToRaster[i] ] = i; } } Void initRasterToPelXY ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth ) { UInt i; UInt* uiTempX = &g_auiRasterToPelX[0]; UInt* uiTempY = &g_auiRasterToPelY[0]; UInt uiMinCUWidth = uiMaxCUWidth >> ( uiMaxDepth - 1 ); UInt uiMinCUHeight = uiMaxCUHeight >> ( uiMaxDepth - 1 ); UInt uiNumPartInWidth = uiMaxCUWidth / uiMinCUWidth; UInt uiNumPartInHeight = uiMaxCUHeight / uiMinCUHeight; uiTempX[0] = 0; uiTempX++; for ( i = 1; i < uiNumPartInWidth; i++ ) { uiTempX[0] = uiTempX[-1] + uiMinCUWidth; uiTempX++; } for ( i = 1; i < uiNumPartInHeight; i++ ) { memcpy(uiTempX, uiTempX-uiNumPartInWidth, sizeof(UInt)*uiNumPartInWidth); uiTempX += uiNumPartInWidth; } for ( i = 1; i < uiNumPartInWidth*uiNumPartInHeight; i++ ) { uiTempY[i] = ( i / uiNumPartInWidth ) * uiMinCUWidth; } } const Int g_quantScales[SCALING_LIST_REM_NUM] = { 26214,23302,20560,18396,16384,14564 }; const Int g_invQuantScales[SCALING_LIST_REM_NUM] = { 40,45,51,57,64,72 }; //-------------------------------------------------------------------------------------------------- //structures #define DEFINE_DST4x4_MATRIX(a,b,c,d) \ { \ { a, b, c, d }, \ { c, c, 0, -c }, \ { d, -a, -c, b }, \ { b, -d, c, -a }, \ } #define DEFINE_DCT4x4_MATRIX(a,b,c) \ { \ { a, a, a, a}, \ { b, c, -c, -b}, \ { a, -a, -a, a}, \ { c, -b, b, -c} \ } #define DEFINE_DCT8x8_MATRIX(a,b,c,d,e,f,g) \ { \ { a, a, a, a, a, a, a, a}, \ { d, e, f, g, -g, -f, -e, -d}, \ { b, c, -c, -b, -b, -c, c, b}, \ { e, -g, -d, -f, f, d, g, -e}, \ { a, -a, -a, a, a, -a, -a, a}, \ { f, -d, g, e, -e, -g, d, -f}, \ { c, -b, b, -c, -c, b, -b, c}, \ { g, -f, e, -d, d, -e, f, -g} \ } #define DEFINE_DCT16x16_MATRIX(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \ { \ { a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a}, \ { h, i, j, k, l, m, n, o, -o, -n, -m, -l, -k, -j, -i, -h}, \ { d, e, f, g, -g, -f, -e, -d, -d, -e, -f, -g, g, f, e, d}, \ { i, l, o, -m, -j, -h, -k, -n, n, k, h, j, m, -o, -l, -i}, \ { b, c, -c, -b, -b, -c, c, b, b, c, -c, -b, -b, -c, c, b}, \ { j, o, -k, -i, -n, l, h, m, -m, -h, -l, n, i, k, -o, -j}, \ { e, -g, -d, -f, f, d, g, -e, -e, g, d, f, -f, -d, -g, e}, \ { k, -m, -i, o, h, n, -j, -l, l, j, -n, -h, -o, i, m, -k}, \ { a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a}, \ { l, -j, -n, h, -o, -i, m, k, -k, -m, i, o, -h, n, j, -l}, \ { f, -d, g, e, -e, -g, d, -f, -f, d, -g, -e, e, g, -d, f}, \ { m, -h, l, n, -i, k, o, -j, j, -o, -k, i, -n, -l, h, -m}, \ { c, -b, b, -c, -c, b, -b, c, c, -b, b, -c, -c, b, -b, c}, \ { n, -k, h, -j, m, o, -l, i, -i, l, -o, -m, j, -h, k, -n}, \ { g, -f, e, -d, d, -e, f, -g, -g, f, -e, d, -d, e, -f, g}, \ { o, -n, m, -l, k, -j, i, -h, h, -i, j, -k, l, -m, n, -o} \ } #define DEFINE_DCT32x32_MATRIX(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E) \ { \ { a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a}, \ { p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, -E, -D, -C, -B, -A, -z, -y, -x, -w, -v, -u, -t, -s, -r, -q, -p}, \ { h, i, j, k, l, m, n, o, -o, -n, -m, -l, -k, -j, -i, -h, -h, -i, -j, -k, -l, -m, -n, -o, o, n, m, l, k, j, i, h}, \ { q, t, w, z, C, -E, -B, -y, -v, -s, -p, -r, -u, -x, -A, -D, D, A, x, u, r, p, s, v, y, B, E, -C, -z, -w, -t, -q}, \ { d, e, f, g, -g, -f, -e, -d, -d, -e, -f, -g, g, f, e, d, d, e, f, g, -g, -f, -e, -d, -d, -e, -f, -g, g, f, e, d}, \ { r, w, B, -D, -y, -t, -p, -u, -z, -E, A, v, q, s, x, C, -C, -x, -s, -q, -v, -A, E, z, u, p, t, y, D, -B, -w, -r}, \ { i, l, o, -m, -j, -h, -k, -n, n, k, h, j, m, -o, -l, -i, -i, -l, -o, m, j, h, k, n, -n, -k, -h, -j, -m, o, l, i}, \ { s, z, -D, -w, -p, -v, -C, A, t, r, y, -E, -x, -q, -u, -B, B, u, q, x, E, -y, -r, -t, -A, C, v, p, w, D, -z, -s}, \ { b, c, -c, -b, -b, -c, c, b, b, c, -c, -b, -b, -c, c, b, b, c, -c, -b, -b, -c, c, b, b, c, -c, -b, -b, -c, c, b}, \ { t, C, -y, -p, -x, D, u, s, B, -z, -q, -w, E, v, r, A, -A, -r, -v, -E, w, q, z, -B, -s, -u, -D, x, p, y, -C, -t}, \ { j, o, -k, -i, -n, l, h, m, -m, -h, -l, n, i, k, -o, -j, -j, -o, k, i, n, -l, -h, -m, m, h, l, -n, -i, -k, o, j}, \ { u, -E, -t, -v, D, s, w, -C, -r, -x, B, q, y, -A, -p, -z, z, p, A, -y, -q, -B, x, r, C, -w, -s, -D, v, t, E, -u}, \ { e, -g, -d, -f, f, d, g, -e, -e, g, d, f, -f, -d, -g, e, e, -g, -d, -f, f, d, g, -e, -e, g, d, f, -f, -d, -g, e}, \ { v, -B, -p, -C, u, w, -A, -q, -D, t, x, -z, -r, -E, s, y, -y, -s, E, r, z, -x, -t, D, q, A, -w, -u, C, p, B, -v}, \ { k, -m, -i, o, h, n, -j, -l, l, j, -n, -h, -o, i, m, -k, -k, m, i, -o, -h, -n, j, l, -l, -j, n, h, o, -i, -m, k}, \ { w, -y, -u, A, s, -C, -q, E, p, D, -r, -B, t, z, -v, -x, x, v, -z, -t, B, r, -D, -p, -E, q, C, -s, -A, u, y, -w}, \ { a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a, a, -a, -a, a}, \ { x, -v, -z, t, B, -r, -D, p, -E, -q, C, s, -A, -u, y, w, -w, -y, u, A, -s, -C, q, E, -p, D, r, -B, -t, z, v, -x}, \ { l, -j, -n, h, -o, -i, m, k, -k, -m, i, o, -h, n, j, -l, -l, j, n, -h, o, i, -m, -k, k, m, -i, -o, h, -n, -j, l}, \ { y, -s, -E, r, -z, -x, t, D, -q, A, w, -u, -C, p, -B, -v, v, B, -p, C, u, -w, -A, q, -D, -t, x, z, -r, E, s, -y}, \ { f, -d, g, e, -e, -g, d, -f, -f, d, -g, -e, e, g, -d, f, f, -d, g, e, -e, -g, d, -f, -f, d, -g, -e, e, g, -d, f}, \ { z, -p, A, y, -q, B, x, -r, C, w, -s, D, v, -t, E, u, -u, -E, t, -v, -D, s, -w, -C, r, -x, -B, q, -y, -A, p, -z}, \ { m, -h, l, n, -i, k, o, -j, j, -o, -k, i, -n, -l, h, -m, -m, h, -l, -n, i, -k, -o, j, -j, o, k, -i, n, l, -h, m}, \ { A, -r, v, -E, -w, q, -z, -B, s, -u, D, x, -p, y, C, -t, t, -C, -y, p, -x, -D, u, -s, B, z, -q, w, E, -v, r, -A}, \ { c, -b, b, -c, -c, b, -b, c, c, -b, b, -c, -c, b, -b, c, c, -b, b, -c, -c, b, -b, c, c, -b, b, -c, -c, b, -b, c}, \ { B, -u, q, -x, E, y, -r, t, -A, -C, v, -p, w, -D, -z, s, -s, z, D, -w, p, -v, C, A, -t, r, -y, -E, x, -q, u, -B}, \ { n, -k, h, -j, m, o, -l, i, -i, l, -o, -m, j, -h, k, -n, -n, k, -h, j, -m, -o, l, -i, i, -l, o, m, -j, h, -k, n}, \ { C, -x, s, -q, v, -A, -E, z, -u, p, -t, y, -D, -B, w, -r, r, -w, B, D, -y, t, -p, u, -z, E, A, -v, q, -s, x, -C}, \ { g, -f, e, -d, d, -e, f, -g, -g, f, -e, d, -d, e, -f, g, g, -f, e, -d, d, -e, f, -g, -g, f, -e, d, -d, e, -f, g}, \ { D, -A, x, -u, r, -p, s, -v, y, -B, E, C, -z, w, -t, q, -q, t, -w, z, -C, -E, B, -y, v, -s, p, -r, u, -x, A, -D}, \ { o, -n, m, -l, k, -j, i, -h, h, -i, j, -k, l, -m, n, -o, -o, n, -m, l, -k, j, -i, h, -h, i, -j, k, -l, m, -n, o}, \ { E, -D, C, -B, A, -z, y, -x, w, -v, u, -t, s, -r, q, -p, p, -q, r, -s, t, -u, v, -w, x, -y, z, -A, B, -C, D, -E} \ } #if JVET_X0048_X0103_FILM_GRAIN #define DEFINE_DCT2_P64_MATRIX(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az, ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz, ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck) \ { \ { aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa, aa }, \ { bf, bg, bh, bi, bj, bk, bl, bm, bn, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, by, bz, ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, -ck, -cj, -ci, -ch, -cg, -cf, -ce, -cd, -cc, -cb, -ca, -bz, -by, -bx, -bw, -bv, -bu, -bt, -bs, -br, -bq, -bp, -bo, -bn, -bm, -bl, -bk, -bj, -bi, -bh, -bg, -bf }, \ { ap, aq, ar, as, at, au, av, aw, ax, ay, az, ba, bb, bc, bd, be, -be, -bd, -bc, -bb, -ba, -az, -ay, -ax, -aw, -av, -au, -at, -as, -ar, -aq, -ap, -ap, -aq, -ar, -as, -at, -au, -av, -aw, -ax, -ay, -az, -ba, -bb, -bc, -bd, -be, be, bd, bc, bb, ba, az, ay, ax, aw, av, au, at, as, ar, aq, ap }, \ { bg, bj, bm, bp, bs, bv, by, cb, ce, ch, ck, -ci, -cf, -cc, -bz, -bw, -bt, -bq, -bn, -bk, -bh, -bf, -bi, -bl, -bo, -br, -bu, -bx, -ca, -cd, -cg, -cj, cj, cg, cd, ca, bx, bu, br, bo, bl, bi, bf, bh, bk, bn, bq, bt, bw, bz, cc, cf, ci, -ck, -ch, -ce, -cb, -by, -bv, -bs, -bp, -bm, -bj, -bg }, \ { ah, ai, aj, ak, al, am, an, ao, -ao, -an, -am, -al, -ak, -aj, -ai, -ah, -ah, -ai, -aj, -ak, -al, -am, -an, -ao, ao, an, am, al, ak, aj, ai, ah, ah, ai, aj, ak, al, am, an, ao, -ao, -an, -am, -al, -ak, -aj, -ai, -ah, -ah, -ai, -aj, -ak, -al, -am, -an, -ao, ao, an, am, al, ak, aj, ai, ah }, \ { bh, bm, br, bw, cb, cg, -ck, -cf, -ca, -bv, -bq, -bl, -bg, -bi, -bn, -bs, -bx, -cc, -ch, cj, ce, bz, bu, bp, bk, bf, bj, bo, bt, by, cd, ci, -ci, -cd, -by, -bt, -bo, -bj, -bf, -bk, -bp, -bu, -bz, -ce, -cj, ch, cc, bx, bs, bn, bi, bg, bl, bq, bv, ca, cf, ck, -cg, -cb, -bw, -br, -bm, -bh }, \ { aq, at, aw, az, bc, -be, -bb, -ay, -av, -as, -ap, -ar, -au, -ax, -ba, -bd, bd, ba, ax, au, ar, ap, as, av, ay, bb, be, -bc, -az, -aw, -at, -aq, -aq, -at, -aw, -az, -bc, be, bb, ay, av, as, ap, ar, au, ax, ba, bd, -bd, -ba, -ax, -au, -ar, -ap, -as, -av, -ay, -bb, -be, bc, az, aw, at, aq }, \ { bi, bp, bw, cd, ck, -ce, -bx, -bq, -bj, -bh, -bo, -bv, -cc, -cj, cf, by, br, bk, bg, bn, bu, cb, ci, -cg, -bz, -bs, -bl, -bf, -bm, -bt, -ca, -ch, ch, ca, bt, bm, bf, bl, bs, bz, cg, -ci, -cb, -bu, -bn, -bg, -bk, -br, -by, -cf, cj, cc, bv, bo, bh, bj, bq, bx, ce, -ck, -cd, -bw, -bp, -bi }, \ { ad, ae, af, ag, -ag, -af, -ae, -ad, -ad, -ae, -af, -ag, ag, af, ae, ad, ad, ae, af, ag, -ag, -af, -ae, -ad, -ad, -ae, -af, -ag, ag, af, ae, ad, ad, ae, af, ag, -ag, -af, -ae, -ad, -ad, -ae, -af, -ag, ag, af, ae, ad, ad, ae, af, ag, -ag, -af, -ae, -ad, -ad, -ae, -af, -ag, ag, af, ae, ad }, \ { bj, bs, cb, ck, -cc, -bt, -bk, -bi, -br, -ca, -cj, cd, bu, bl, bh, bq, bz, ci, -ce, -bv, -bm, -bg, -bp, -by, -ch, cf, bw, bn, bf, bo, bx, cg, -cg, -bx, -bo, -bf, -bn, -bw, -cf, ch, by, bp, bg, bm, bv, ce, -ci, -bz, -bq, -bh, -bl, -bu, -cd, cj, ca, br, bi, bk, bt, cc, -ck, -cb, -bs, -bj }, \ { ar, aw, bb, -bd, -ay, -at, -ap, -au, -az, -be, ba, av, aq, as, ax, bc, -bc, -ax, -as, -aq, -av, -ba, be, az, au, ap, at, ay, bd, -bb, -aw, -ar, -ar, -aw, -bb, bd, ay, at, ap, au, az, be, -ba, -av, -aq, -as, -ax, -bc, bc, ax, as, aq, av, ba, -be, -az, -au, -ap, -at, -ay, -bd, bb, aw, ar }, \ { bk, bv, cg, -ce, -bt, -bi, -bm, -bx, -ci, cc, br, bg, bo, bz, ck, -ca, -bp, -bf, -bq, -cb, cj, by, bn, bh, bs, cd, -ch, -bw, -bl, -bj, -bu, -cf, cf, bu, bj, bl, bw, ch, -cd, -bs, -bh, -bn, -by, -cj, cb, bq, bf, bp, ca, -ck, -bz, -bo, -bg, -br, -cc, ci, bx, bm, bi, bt, ce, -cg, -bv, -bk }, \ { ai, al, ao, -am, -aj, -ah, -ak, -an, an, ak, ah, aj, am, -ao, -al, -ai, -ai, -al, -ao, am, aj, ah, ak, an, -an, -ak, -ah, -aj, -am, ao, al, ai, ai, al, ao, -am, -aj, -ah, -ak, -an, an, ak, ah, aj, am, -ao, -al, -ai, -ai, -al, -ao, am, aj, ah, ak, an, -an, -ak, -ah, -aj, -am, ao, al, ai }, \ { bl, by, -ck, -bx, -bk, -bm, -bz, cj, bw, bj, bn, ca, -ci, -bv, -bi, -bo, -cb, ch, bu, bh, bp, cc, -cg, -bt, -bg, -bq, -cd, cf, bs, bf, br, ce, -ce, -br, -bf, -bs, -cf, cd, bq, bg, bt, cg, -cc, -bp, -bh, -bu, -ch, cb, bo, bi, bv, ci, -ca, -bn, -bj, -bw, -cj, bz, bm, bk, bx, ck, -by, -bl }, \ { as, az, -bd, -aw, -ap, -av, -bc, ba, at, ar, ay, -be, -ax, -aq, -au, -bb, bb, au, aq, ax, be, -ay, -ar, -at, -ba, bc, av, ap, aw, bd, -az, -as, -as, -az, bd, aw, ap, av, bc, -ba, -at, -ar, -ay, be, ax, aq, au, bb, -bb, -au, -aq, -ax, -be, ay, ar, at, ba, -bc, -av, -ap, -aw, -bd, az, as }, \ { bm, cb, -cf, -bq, -bi, -bx, cj, bu, bf, bt, ci, -by, -bj, -bp, -ce, cc, bn, bl, ca, -cg, -br, -bh, -bw, ck, bv, bg, bs, ch, -bz, -bk, -bo, -cd, cd, bo, bk, bz, -ch, -bs, -bg, -bv, -ck, bw, bh, br, cg, -ca, -bl, -bn, -cc, ce, bp, bj, by, -ci, -bt, -bf, -bu, -cj, bx, bi, bq, cf, -cb, -bm }, \ { ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab, ab, ac, -ac, -ab, -ab, -ac, ac, ab }, \ { bn, ce, -ca, -bj, -br, -ci, bw, bf, bv, -cj, -bs, -bi, -bz, cf, bo, bm, cd, -cb, -bk, -bq, -ch, bx, bg, bu, -ck, -bt, -bh, -by, cg, bp, bl, cc, -cc, -bl, -bp, -cg, by, bh, bt, ck, -bu, -bg, -bx, ch, bq, bk, cb, -cd, -bm, -bo, -cf, bz, bi, bs, cj, -bv, -bf, -bw, ci, br, bj, ca, -ce, -bn }, \ { at, bc, -ay, -ap, -ax, bd, au, as, bb, -az, -aq, -aw, be, av, ar, ba, -ba, -ar, -av, -be, aw, aq, az, -bb, -as, -au, -bd, ax, ap, ay, -bc, -at, -at, -bc, ay, ap, ax, -bd, -au, -as, -bb, az, aq, aw, -be, -av, -ar, -ba, ba, ar, av, be, -aw, -aq, -az, bb, as, au, bd, -ax, -ap, -ay, bc, at }, \ { bo, ch, -bv, -bh, -ca, cc, bj, bt, -cj, -bq, -bm, -cf, bx, bf, by, -ce, -bl, -br, -ck, bs, bk, cd, -bz, -bg, -bw, cg, bn, bp, ci, -bu, -bi, -cb, cb, bi, bu, -ci, -bp, -bn, -cg, bw, bg, bz, -cd, -bk, -bs, ck, br, bl, ce, -by, -bf, -bx, cf, bm, bq, cj, -bt, -bj, -cc, ca, bh, bv, -ch, -bo }, \ { aj, ao, -ak, -ai, -an, al, ah, am, -am, -ah, -al, an, ai, ak, -ao, -aj, -aj, -ao, ak, ai, an, -al, -ah, -am, am, ah, al, -an, -ai, -ak, ao, aj, aj, ao, -ak, -ai, -an, al, ah, am, -am, -ah, -al, an, ai, ak, -ao, -aj, -aj, -ao, ak, ai, an, -al, -ah, -am, am, ah, al, -an, -ai, -ak, ao, aj }, \ { bp, ck, -bq, -bo, -cj, br, bn, ci, -bs, -bm, -ch, bt, bl, cg, -bu, -bk, -cf, bv, bj, ce, -bw, -bi, -cd, bx, bh, cc, -by, -bg, -cb, bz, bf, ca, -ca, -bf, -bz, cb, bg, by, -cc, -bh, -bx, cd, bi, bw, -ce, -bj, -bv, cf, bk, bu, -cg, -bl, -bt, ch, bm, bs, -ci, -bn, -br, cj, bo, bq, -ck, -bp }, \ { au, -be, -at, -av, bd, as, aw, -bc, -ar, -ax, bb, aq, ay, -ba, -ap, -az, az, ap, ba, -ay, -aq, -bb, ax, ar, bc, -aw, -as, -bd, av, at, be, -au, -au, be, at, av, -bd, -as, -aw, bc, ar, ax, -bb, -aq, -ay, ba, ap, az, -az, -ap, -ba, ay, aq, bb, -ax, -ar, -bc, aw, as, bd, -av, -at, -be, au }, \ { bq, -ci, -bl, -bv, cd, bg, ca, -by, -bi, -cf, bt, bn, ck, -bo, -bs, cg, bj, bx, -cb, -bf, -cc, bw, bk, ch, -br, -bp, cj, bm, bu, -ce, -bh, -bz, bz, bh, ce, -bu, -bm, -cj, bp, br, -ch, -bk, -bw, cc, bf, cb, -bx, -bj, -cg, bs, bo, -ck, -bn, -bt, cf, bi, by, -ca, -bg, -cd, bv, bl, ci, -bq }, \ { ae, -ag, -ad, -af, af, ad, ag, -ae, -ae, ag, ad, af, -af, -ad, -ag, ae, ae, -ag, -ad, -af, af, ad, ag, -ae, -ae, ag, ad, af, -af, -ad, -ag, ae, ae, -ag, -ad, -af, af, ad, ag, -ae, -ae, ag, ad, af, -af, -ad, -ag, ae, ae, -ag, -ad, -af, af, ad, ag, -ae, -ae, ag, ad, af, -af, -ad, -ag, ae }, \ { br, -cf, -bg, -cc, bu, bo, -ci, -bj, -bz, bx, bl, ck, -bm, -bw, ca, bi, ch, -bp, -bt, cd, bf, ce, -bs, -bq, cg, bh, cb, -bv, -bn, cj, bk, by, -by, -bk, -cj, bn, bv, -cb, -bh, -cg, bq, bs, -ce, -bf, -cd, bt, bp, -ch, -bi, -ca, bw, bm, -ck, -bl, -bx, bz, bj, ci, -bo, -bu, cc, bg, cf, -br }, \ { av, -bb, -ap, -bc, au, aw, -ba, -aq, -bd, at, ax, -az, -ar, -be, as, ay, -ay, -as, be, ar, az, -ax, -at, bd, aq, ba, -aw, -au, bc, ap, bb, -av, -av, bb, ap, bc, -au, -aw, ba, aq, bd, -at, -ax, az, ar, be, -as, -ay, ay, as, -be, -ar, -az, ax, at, -bd, -aq, -ba, aw, au, -bc, -ap, -bb, av }, \ { bs, -cc, -bi, -cj, bl, bz, -bv, -bp, cf, bf, cg, -bo, -bw, by, bm, -ci, -bh, -cd, br, bt, -cb, -bj, -ck, bk, ca, -bu, -bq, ce, bg, ch, -bn, -bx, bx, bn, -ch, -bg, -ce, bq, bu, -ca, -bk, ck, bj, cb, -bt, -br, cd, bh, ci, -bm, -by, bw, bo, -cg, -bf, -cf, bp, bv, -bz, -bl, cj, bi, cc, -bs }, \ { ak, -am, -ai, ao, ah, an, -aj, -al, al, aj, -an, -ah, -ao, ai, am, -ak, -ak, am, ai, -ao, -ah, -an, aj, al, -al, -aj, an, ah, ao, -ai, -am, ak, ak, -am, -ai, ao, ah, an, -aj, -al, al, aj, -an, -ah, -ao, ai, am, -ak, -ak, am, ai, -ao, -ah, -an, aj, al, -al, -aj, an, ah, ao, -ai, -am, ak }, \ { bt, -bz, -bn, cf, bh, ck, -bi, -ce, bo, by, -bu, -bs, ca, bm, -cg, -bg, -cj, bj, cd, -bp, -bx, bv, br, -cb, -bl, ch, bf, ci, -bk, -cc, bq, bw, -bw, -bq, cc, bk, -ci, -bf, -ch, bl, cb, -br, -bv, bx, bp, -cd, -bj, cj, bg, cg, -bm, -ca, bs, bu, -by, -bo, ce, bi, -ck, -bh, -cf, bn, bz, -bt }, \ { aw, -ay, -au, ba, as, -bc, -aq, be, ap, bd, -ar, -bb, at, az, -av, -ax, ax, av, -az, -at, bb, ar, -bd, -ap, -be, aq, bc, -as, -ba, au, ay, -aw, -aw, ay, au, -ba, -as, bc, aq, -be, -ap, -bd, ar, bb, -at, -az, av, ax, -ax, -av, az, at, -bb, -ar, bd, ap, be, -aq, -bc, as, ba, -au, -ay, aw }, \ { bu, -bw, -bs, by, bq, -ca, -bo, cc, bm, -ce, -bk, cg, bi, -ci, -bg, ck, bf, cj, -bh, -ch, bj, cf, -bl, -cd, bn, cb, -bp, -bz, br, bx, -bt, -bv, bv, bt, -bx, -br, bz, bp, -cb, -bn, cd, bl, -cf, -bj, ch, bh, -cj, -bf, -ck, bg, ci, -bi, -cg, bk, ce, -bm, -cc, bo, ca, -bq, -by, bs, bw, -bu }, \ { aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa, aa, -aa, -aa, aa }, \ { bv, -bt, -bx, br, bz, -bp, -cb, bn, cd, -bl, -cf, bj, ch, -bh, -cj, bf, -ck, -bg, ci, bi, -cg, -bk, ce, bm, -cc, -bo, ca, bq, -by, -bs, bw, bu, -bu, -bw, bs, by, -bq, -ca, bo, cc, -bm, -ce, bk, cg, -bi, -ci, bg, ck, -bf, cj, bh, -ch, -bj, cf, bl, -cd, -bn, cb, bp, -bz, -br, bx, bt, -bv }, \ { ax, -av, -az, at, bb, -ar, -bd, ap, -be, -aq, bc, as, -ba, -au, ay, aw, -aw, -ay, au, ba, -as, -bc, aq, be, -ap, bd, ar, -bb, -at, az, av, -ax, -ax, av, az, -at, -bb, ar, bd, -ap, be, aq, -bc, -as, ba, au, -ay, -aw, aw, ay, -au, -ba, as, bc, -aq, -be, ap, -bd, -ar, bb, at, -az, -av, ax }, \ { bw, -bq, -cc, bk, ci, -bf, ch, bl, -cb, -br, bv, bx, -bp, -cd, bj, cj, -bg, cg, bm, -ca, -bs, bu, by, -bo, -ce, bi, ck, -bh, cf, bn, -bz, -bt, bt, bz, -bn, -cf, bh, -ck, -bi, ce, bo, -by, -bu, bs, ca, -bm, -cg, bg, -cj, -bj, cd, bp, -bx, -bv, br, cb, -bl, -ch, bf, -ci, -bk, cc, bq, -bw }, \ { al, -aj, -an, ah, -ao, -ai, am, ak, -ak, -am, ai, ao, -ah, an, aj, -al, -al, aj, an, -ah, ao, ai, -am, -ak, ak, am, -ai, -ao, ah, -an, -aj, al, al, -aj, -an, ah, -ao, -ai, am, ak, -ak, -am, ai, ao, -ah, an, aj, -al, -al, aj, an, -ah, ao, ai, -am, -ak, ak, am, -ai, -ao, ah, -an, -aj, al }, \ { bx, -bn, -ch, bg, -ce, -bq, bu, ca, -bk, -ck, bj, -cb, -bt, br, cd, -bh, ci, bm, -by, -bw, bo, cg, -bf, cf, bp, -bv, -bz, bl, cj, -bi, cc, bs, -bs, -cc, bi, -cj, -bl, bz, bv, -bp, -cf, bf, -cg, -bo, bw, by, -bm, -ci, bh, -cd, -br, bt, cb, -bj, ck, bk, -ca, -bu, bq, ce, -bg, ch, bn, -bx }, \ { ay, -as, -be, ar, -az, -ax, at, bd, -aq, ba, aw, -au, -bc, ap, -bb, -av, av, bb, -ap, bc, au, -aw, -ba, aq, -bd, -at, ax, az, -ar, be, as, -ay, -ay, as, be, -ar, az, ax, -at, -bd, aq, -ba, -aw, au, bc, -ap, bb, av, -av, -bb, ap, -bc, -au, aw, ba, -aq, bd, at, -ax, -az, ar, -be, -as, ay }, \ { by, -bk, cj, bn, -bv, -cb, bh, -cg, -bq, bs, ce, -bf, cd, bt, -bp, -ch, bi, -ca, -bw, bm, ck, -bl, bx, bz, -bj, ci, bo, -bu, -cc, bg, -cf, -br, br, cf, -bg, cc, bu, -bo, -ci, bj, -bz, -bx, bl, -ck, -bm, bw, ca, -bi, ch, bp, -bt, -cd, bf, -ce, -bs, bq, cg, -bh, cb, bv, -bn, -cj, bk, -by }, \ { af, -ad, ag, ae, -ae, -ag, ad, -af, -af, ad, -ag, -ae, ae, ag, -ad, af, af, -ad, ag, ae, -ae, -ag, ad, -af, -af, ad, -ag, -ae, ae, ag, -ad, af, af, -ad, ag, ae, -ae, -ag, ad, -af, -af, ad, -ag, -ae, ae, ag, -ad, af, af, -ad, ag, ae, -ae, -ag, ad, -af, -af, ad, -ag, -ae, ae, ag, -ad, af }, \ { bz, -bh, ce, bu, -bm, cj, bp, -br, -ch, bk, -bw, -cc, bf, -cb, -bx, bj, -cg, -bs, bo, ck, -bn, bt, cf, -bi, by, ca, -bg, cd, bv, -bl, ci, bq, -bq, -ci, bl, -bv, -cd, bg, -ca, -by, bi, -cf, -bt, bn, -ck, -bo, bs, cg, -bj, bx, cb, -bf, cc, bw, -bk, ch, br, -bp, -cj, bm, -bu, -ce, bh, -bz }, \ { az, -ap, ba, ay, -aq, bb, ax, -ar, bc, aw, -as, bd, av, -at, be, au, -au, -be, at, -av, -bd, as, -aw, -bc, ar, -ax, -bb, aq, -ay, -ba, ap, -az, -az, ap, -ba, -ay, aq, -bb, -ax, ar, -bc, -aw, as, -bd, -av, at, -be, -au, au, be, -at, av, bd, -as, aw, bc, -ar, ax, bb, -aq, ay, ba, -ap, az }, \ { ca, -bf, bz, cb, -bg, by, cc, -bh, bx, cd, -bi, bw, ce, -bj, bv, cf, -bk, bu, cg, -bl, bt, ch, -bm, bs, ci, -bn, br, cj, -bo, bq, ck, -bp, bp, -ck, -bq, bo, -cj, -br, bn, -ci, -bs, bm, -ch, -bt, bl, -cg, -bu, bk, -cf, -bv, bj, -ce, -bw, bi, -cd, -bx, bh, -cc, -by, bg, -cb, -bz, bf, -ca }, \ { am, -ah, al, an, -ai, ak, ao, -aj, aj, -ao, -ak, ai, -an, -al, ah, -am, -am, ah, -al, -an, ai, -ak, -ao, aj, -aj, ao, ak, -ai, an, al, -ah, am, am, -ah, al, an, -ai, ak, ao, -aj, aj, -ao, -ak, ai, -an, -al, ah, -am, -am, ah, -al, -an, ai, -ak, -ao, aj, -aj, ao, ak, -ai, an, al, -ah, am }, \ { cb, -bi, bu, ci, -bp, bn, -cg, -bw, bg, -bz, -cd, bk, -bs, -ck, br, -bl, ce, by, -bf, bx, cf, -bm, bq, -cj, -bt, bj, -cc, -ca, bh, -bv, -ch, bo, -bo, ch, bv, -bh, ca, cc, -bj, bt, cj, -bq, bm, -cf, -bx, bf, -by, -ce, bl, -br, ck, bs, -bk, cd, bz, -bg, bw, cg, -bn, bp, -ci, -bu, bi, -cb }, \ { ba, -ar, av, -be, -aw, aq, -az, -bb, as, -au, bd, ax, -ap, ay, bc, -at, at, -bc, -ay, ap, -ax, -bd, au, -as, bb, az, -aq, aw, be, -av, ar, -ba, -ba, ar, -av, be, aw, -aq, az, bb, -as, au, -bd, -ax, ap, -ay, -bc, at, -at, bc, ay, -ap, ax, bd, -au, as, -bb, -az, aq, -aw, -be, av, -ar, ba }, \ { cc, -bl, bp, -cg, -by, bh, -bt, ck, bu, -bg, bx, ch, -bq, bk, -cb, -cd, bm, -bo, cf, bz, -bi, bs, -cj, -bv, bf, -bw, -ci, br, -bj, ca, ce, -bn, bn, -ce, -ca, bj, -br, ci, bw, -bf, bv, cj, -bs, bi, -bz, -cf, bo, -bm, cd, cb, -bk, bq, -ch, -bx, bg, -bu, -ck, bt, -bh, by, cg, -bp, bl, -cc }, \ { ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac, ac, -ab, ab, -ac, -ac, ab, -ab, ac }, \ { cd, -bo, bk, -bz, -ch, bs, -bg, bv, -ck, -bw, bh, -br, cg, ca, -bl, bn, -cc, -ce, bp, -bj, by, ci, -bt, bf, -bu, cj, bx, -bi, bq, -cf, -cb, bm, -bm, cb, cf, -bq, bi, -bx, -cj, bu, -bf, bt, -ci, -by, bj, -bp, ce, cc, -bn, bl, -ca, -cg, br, -bh, bw, ck, -bv, bg, -bs, ch, bz, -bk, bo, -cd }, \ { bb, -au, aq, -ax, be, ay, -ar, at, -ba, -bc, av, -ap, aw, -bd, -az, as, -as, az, bd, -aw, ap, -av, bc, ba, -at, ar, -ay, -be, ax, -aq, au, -bb, -bb, au, -aq, ax, -be, -ay, ar, -at, ba, bc, -av, ap, -aw, bd, az, -as, as, -az, -bd, aw, -ap, av, -bc, -ba, at, -ar, ay, be, -ax, aq, -au, bb }, \ { ce, -br, bf, -bs, cf, cd, -bq, bg, -bt, cg, cc, -bp, bh, -bu, ch, cb, -bo, bi, -bv, ci, ca, -bn, bj, -bw, cj, bz, -bm, bk, -bx, ck, by, -bl, bl, -by, -ck, bx, -bk, bm, -bz, -cj, bw, -bj, bn, -ca, -ci, bv, -bi, bo, -cb, -ch, bu, -bh, bp, -cc, -cg, bt, -bg, bq, -cd, -cf, bs, -bf, br, -ce }, \ { an, -ak, ah, -aj, am, ao, -al, ai, -ai, al, -ao, -am, aj, -ah, ak, -an, -an, ak, -ah, aj, -am, -ao, al, -ai, ai, -al, ao, am, -aj, ah, -ak, an, an, -ak, ah, -aj, am, ao, -al, ai, -ai, al, -ao, -am, aj, -ah, ak, -an, -an, ak, -ah, aj, -am, -ao, al, -ai, ai, -al, ao, am, -aj, ah, -ak, an }, \ { cf, -bu, bj, -bl, bw, -ch, -cd, bs, -bh, bn, -by, cj, cb, -bq, bf, -bp, ca, ck, -bz, bo, -bg, br, -cc, -ci, bx, -bm, bi, -bt, ce, cg, -bv, bk, -bk, bv, -cg, -ce, bt, -bi, bm, -bx, ci, cc, -br, bg, -bo, bz, -ck, -ca, bp, -bf, bq, -cb, -cj, by, -bn, bh, -bs, cd, ch, -bw, bl, -bj, bu, -cf }, \ { bc, -ax, as, -aq, av, -ba, -be, az, -au, ap, -at, ay, -bd, -bb, aw, -ar, ar, -aw, bb, bd, -ay, at, -ap, au, -az, be, ba, -av, aq, -as, ax, -bc, -bc, ax, -as, aq, -av, ba, be, -az, au, -ap, at, -ay, bd, bb, -aw, ar, -ar, aw, -bb, -bd, ay, -at, ap, -au, az, -be, -ba, av, -aq, as, -ax, bc }, \ { cg, -bx, bo, -bf, bn, -bw, cf, ch, -by, bp, -bg, bm, -bv, ce, ci, -bz, bq, -bh, bl, -bu, cd, cj, -ca, br, -bi, bk, -bt, cc, ck, -cb, bs, -bj, bj, -bs, cb, -ck, -cc, bt, -bk, bi, -br, ca, -cj, -cd, bu, -bl, bh, -bq, bz, -ci, -ce, bv, -bm, bg, -bp, by, -ch, -cf, bw, -bn, bf, -bo, bx, -cg }, \ { ag, -af, ae, -ad, ad, -ae, af, -ag, -ag, af, -ae, ad, -ad, ae, -af, ag, ag, -af, ae, -ad, ad, -ae, af, -ag, -ag, af, -ae, ad, -ad, ae, -af, ag, ag, -af, ae, -ad, ad, -ae, af, -ag, -ag, af, -ae, ad, -ad, ae, -af, ag, ag, -af, ae, -ad, ad, -ae, af, -ag, -ag, af, -ae, ad, -ad, ae, -af, ag }, \ { ch, -ca, bt, -bm, bf, -bl, bs, -bz, cg, ci, -cb, bu, -bn, bg, -bk, br, -by, cf, cj, -cc, bv, -bo, bh, -bj, bq, -bx, ce, ck, -cd, bw, -bp, bi, -bi, bp, -bw, cd, -ck, -ce, bx, -bq, bj, -bh, bo, -bv, cc, -cj, -cf, by, -br, bk, -bg, bn, -bu, cb, -ci, -cg, bz, -bs, bl, -bf, bm, -bt, ca, -ch }, \ { bd, -ba, ax, -au, ar, -ap, as, -av, ay, -bb, be, bc, -az, aw, -at, aq, -aq, at, -aw, az, -bc, -be, bb, -ay, av, -as, ap, -ar, au, -ax, ba, -bd, -bd, ba, -ax, au, -ar, ap, -as, av, -ay, bb, -be, -bc, az, -aw, at, -aq, aq, -at, aw, -az, bc, be, -bb, ay, -av, as, -ap, ar, -au, ax, -ba, bd }, \ { ci, -cd, by, -bt, bo, -bj, bf, -bk, bp, -bu, bz, -ce, cj, ch, -cc, bx, -bs, bn, -bi, bg, -bl, bq, -bv, ca, -cf, ck, cg, -cb, bw, -br, bm, -bh, bh, -bm, br, -bw, cb, -cg, -ck, cf, -ca, bv, -bq, bl, -bg, bi, -bn, bs, -bx, cc, -ch, -cj, ce, -bz, bu, -bp, bk, -bf, bj, -bo, bt, -by, cd, -ci }, \ { ao, -an, am, -al, ak, -aj, ai, -ah, ah, -ai, aj, -ak, al, -am, an, -ao, -ao, an, -am, al, -ak, aj, -ai, ah, -ah, ai, -aj, ak, -al, am, -an, ao, ao, -an, am, -al, ak, -aj, ai, -ah, ah, -ai, aj, -ak, al, -am, an, -ao, -ao, an, -am, al, -ak, aj, -ai, ah, -ah, ai, -aj, ak, -al, am, -an, ao }, \ { cj, -cg, cd, -ca, bx, -bu, br, -bo, bl, -bi, bf, -bh, bk, -bn, bq, -bt, bw, -bz, cc, -cf, ci, ck, -ch, ce, -cb, by, -bv, bs, -bp, bm, -bj, bg, -bg, bj, -bm, bp, -bs, bv, -by, cb, -ce, ch, -ck, -ci, cf, -cc, bz, -bw, bt, -bq, bn, -bk, bh, -bf, bi, -bl, bo, -br, bu, -bx, ca, -cd, cg, -cj }, \ { be, -bd, bc, -bb, ba, -az, ay, -ax, aw, -av, au, -at, as, -ar, aq, -ap, ap, -aq, ar, -as, at, -au, av, -aw, ax, -ay, az, -ba, bb, -bc, bd, -be, -be, bd, -bc, bb, -ba, az, -ay, ax, -aw, av, -au, at, -as, ar, -aq, ap, -ap, aq, -ar, as, -at, au, -av, aw, -ax, ay, -az, ba, -bb, bc, -bd, be }, \ { ck, -cj, ci, -ch, cg, -cf, ce, -cd, cc, -cb, ca, -bz, by, -bx, bw, -bv, bu, -bt, bs, -br, bq, -bp, bo, -bn, bm, -bl, bk, -bj, bi, -bh, bg, -bf, bf, -bg, bh, -bi, bj, -bk, bl, -bm, bn, -bo, bp, -bq, br, -bs, bt, -bu, bv, -bw, bx, -by, bz, -ca, cb, -cc, cd, -ce, cf, -cg, ch, -ci, cj, -ck }, \ } #endif //-------------------------------------------------------------------------------------------------- //coefficients #if RExt__HIGH_PRECISION_FORWARD_TRANSFORM const TMatrixCoeff g_aiT4 [TRANSFORM_NUMBER_OF_DIRECTIONS][4][4] = { DEFINE_DCT4x4_MATRIX (16384, 21266, 9224), DEFINE_DCT4x4_MATRIX ( 64, 83, 36) }; const TMatrixCoeff g_aiT8 [TRANSFORM_NUMBER_OF_DIRECTIONS][8][8] = { DEFINE_DCT8x8_MATRIX (16384, 21266, 9224, 22813, 19244, 12769, 4563), DEFINE_DCT8x8_MATRIX ( 64, 83, 36, 89, 75, 50, 18) }; const TMatrixCoeff g_aiT16[TRANSFORM_NUMBER_OF_DIRECTIONS][16][16] = { DEFINE_DCT16x16_MATRIX(16384, 21266, 9224, 22813, 19244, 12769, 4563, 23120, 22063, 20450, 17972, 14642, 11109, 6446, 2316), DEFINE_DCT16x16_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9) }; const TMatrixCoeff g_aiT32[TRANSFORM_NUMBER_OF_DIRECTIONS][32][32] = { DEFINE_DCT32x32_MATRIX(16384, 21266, 9224, 22813, 19244, 12769, 4563, 23120, 22063, 20450, 17972, 14642, 11109, 6446, 2316, 23106, 22852, 22445, 21848, 20995, 19810, 18601, 17143, 15718, 13853, 11749, 9846, 7908, 5573, 3281, 946), DEFINE_DCT32x32_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4) }; #if JVET_X0048_X0103_FILM_GRAIN // dct-2 for film grain synthesis and analysis (dct2 64x64 as in vvc) const TMatrixCoeff g_aiT64[TRANSFORM_NUMBER_OF_DIRECTIONS][64][64] = { DEFINE_DCT2_P64_MATRIX(16384, 21266, 9224, 22813, 19244, 12769, 4563, 23129, 22063, 20450, 17972, 14642, 11109, 6446, 2316, 23106, 22852, 22445, 21848, 20995, 19810, 18601, 17143, 15718, 13853, 11749, 9846, 7908, 5573, 3281, 946, 23360, 23053, 23048, 23023, 22610, 22339, 21936, 21502, 21266, 20730, 20251, 19726, 18731, 18201, 17638, 16604, 15881, 15084, 14322, 13340, 12238, 11330, 10493, 9428, 8426, 7100, 6151, 5101, 3848, 2734, 1754, 574), DEFINE_DCT2_P64_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, 91, 90, 90, 90, 88, 87, 86, 84, 83, 81, 79, 77, 73, 71, 69, 65, 62, 59, 56, 52, 48, 44, 41, 37, 33, 28, 24, 20, 15, 11, 7, 2) }; #endif const TMatrixCoeff g_as_DST_MAT_4[TRANSFORM_NUMBER_OF_DIRECTIONS][4][4] = { DEFINE_DST4x4_MATRIX( 7424, 14081, 18893, 21505), DEFINE_DST4x4_MATRIX( 29, 55, 74, 84) }; #else const TMatrixCoeff g_aiT4 [TRANSFORM_NUMBER_OF_DIRECTIONS][4][4] = { DEFINE_DCT4x4_MATRIX ( 64, 83, 36), DEFINE_DCT4x4_MATRIX ( 64, 83, 36) }; const TMatrixCoeff g_aiT8 [TRANSFORM_NUMBER_OF_DIRECTIONS][8][8] = { DEFINE_DCT8x8_MATRIX ( 64, 83, 36, 89, 75, 50, 18), DEFINE_DCT8x8_MATRIX ( 64, 83, 36, 89, 75, 50, 18) }; const TMatrixCoeff g_aiT16[TRANSFORM_NUMBER_OF_DIRECTIONS][16][16] = { DEFINE_DCT16x16_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9), DEFINE_DCT16x16_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9) }; const TMatrixCoeff g_aiT32[TRANSFORM_NUMBER_OF_DIRECTIONS][32][32] = { DEFINE_DCT32x32_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4), DEFINE_DCT32x32_MATRIX( 64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4) }; #if JVET_X0048_X0103_FILM_GRAIN // dct-2 for film grain synthesis and analysis (dct2 64x64 as in vvc) const TMatrixCoeff g_aiT64[TRANSFORM_NUMBER_OF_DIRECTIONS][64][64] = { DEFINE_DCT2_P64_MATRIX(64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, 91, 90, 90, 90, 88, 87, 86, 84, 83, 81, 79, 77, 73, 71, 69, 65, 62, 59, 56, 52, 48, 44, 41, 37, 33, 28, 24, 20, 15, 11, 7, 2), DEFINE_DCT2_P64_MATRIX(64, 83, 36, 89, 75, 50, 18, 90, 87, 80, 70, 57, 43, 25, 9, 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, 91, 90, 90, 90, 88, 87, 86, 84, 83, 81, 79, 77, 73, 71, 69, 65, 62, 59, 56, 52, 48, 44, 41, 37, 33, 28, 24, 20, 15, 11, 7, 2) }; #endif const TMatrixCoeff g_as_DST_MAT_4[TRANSFORM_NUMBER_OF_DIRECTIONS][4][4] = { DEFINE_DST4x4_MATRIX( 29, 55, 74, 84), DEFINE_DST4x4_MATRIX( 29, 55, 74, 84) }; #endif //-------------------------------------------------------------------------------------------------- #undef DEFINE_DST4x4_MATRIX #undef DEFINE_DCT4x4_MATRIX #undef DEFINE_DCT8x8_MATRIX #undef DEFINE_DCT16x16_MATRIX #undef DEFINE_DCT32x32_MATRIX //-------------------------------------------------------------------------------------------------- const UChar g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize]= { //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,29,30,31,32,33,33,34,34,35,35,36,36,37,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,51,51,51,51,51,51 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,51,51,51,51,51,51 } }; // ==================================================================================================================== // Intra prediction // ==================================================================================================================== const UChar g_aucIntraModeNumFast_UseMPM[MAX_CU_DEPTH] = { 3, // 2x2 8, // 4x4 8, // 8x8 3, // 16x16 3, // 32x32 3 // 64x64 }; const UChar g_aucIntraModeNumFast_NotUseMPM[MAX_CU_DEPTH] = { 3, // 2x2 9, // 4x4 9, // 8x8 4, // 16x16 33 4, // 32x32 33 5 // 64x64 33 }; const UChar g_chroma422IntraAngleMappingTable[NUM_INTRA_MODE] = //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, DM { 0, 1, 2, 2, 2, 2, 3, 5, 7, 8, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31, DM_CHROMA_IDX}; // ==================================================================================================================== // Misc. // ==================================================================================================================== SChar g_aucConvertToBit [ MAX_CU_SIZE+1 ]; #if ENC_DEC_TRACE FILE* g_hTrace = NULL; // Set to NULL to open up a file. Set to stdout to use the current output const Bool g_bEncDecTraceEnable = true; const Bool g_bEncDecTraceDisable = false; Bool g_HLSTraceEnable = true; Bool g_bJustDoIt = false; UInt64 g_nSymbolCounter = 0; #endif // ==================================================================================================================== // Scanning order & context model mapping // ==================================================================================================================== // scanning order table UInt* g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][ MAX_CU_DEPTH ][ MAX_CU_DEPTH ]; const UInt ctxIndMap4x4[4*4] = { 0, 1, 4, 5, 2, 3, 4, 5, 6, 6, 8, 8, 7, 7, 8, 8 }; const UInt g_uiMinInGroup[ LAST_SIGNIFICANT_GROUPS ] = {0,1,2,3,4,6,8,12,16,24}; const UInt g_uiGroupIdx[ MAX_TU_SIZE ] = {0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9}; const TChar *MatrixType[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM] = { { "INTRA4X4_LUMA", "INTRA4X4_CHROMAU", "INTRA4X4_CHROMAV", "INTER4X4_LUMA", "INTER4X4_CHROMAU", "INTER4X4_CHROMAV" }, { "INTRA8X8_LUMA", "INTRA8X8_CHROMAU", "INTRA8X8_CHROMAV", "INTER8X8_LUMA", "INTER8X8_CHROMAU", "INTER8X8_CHROMAV" }, { "INTRA16X16_LUMA", "INTRA16X16_CHROMAU", "INTRA16X16_CHROMAV", "INTER16X16_LUMA", "INTER16X16_CHROMAU", "INTER16X16_CHROMAV" }, { "INTRA32X32_LUMA", "INTRA32X32_CHROMAU_FROM16x16_CHROMAU", "INTRA32X32_CHROMAV_FROM16x16_CHROMAV", "INTER32X32_LUMA", "INTER32X32_CHROMAU_FROM16x16_CHROMAU", "INTER32X32_CHROMAV_FROM16x16_CHROMAV" }, }; const TChar *MatrixType_DC[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM] = { { }, { }, { "INTRA16X16_LUMA_DC", "INTRA16X16_CHROMAU_DC", "INTRA16X16_CHROMAV_DC", "INTER16X16_LUMA_DC", "INTER16X16_CHROMAU_DC", "INTER16X16_CHROMAV_DC" }, { "INTRA32X32_LUMA_DC", "INTRA32X32_CHROMAU_DC_FROM16x16_CHROMAU", "INTRA32X32_CHROMAV_DC_FROM16x16_CHROMAV", "INTER32X32_LUMA_DC", "INTER32X32_CHROMAU_DC_FROM16x16_CHROMAU", "INTER32X32_CHROMAV_DC_FROM16x16_CHROMAV" }, }; const Int g_quantTSDefault4x4[4*4] = { 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16 }; const Int g_quantIntraDefault8x8[8*8] = { 16,16,16,16,17,18,21,24, 16,16,16,16,17,19,22,25, 16,16,17,18,20,22,25,29, 16,16,18,21,24,27,31,36, 17,17,20,24,30,35,41,47, 18,19,22,27,35,44,54,65, 21,22,25,31,41,54,70,88, 24,25,29,36,47,65,88,115 }; const Int g_quantInterDefault8x8[8*8] = { 16,16,16,16,17,18,20,24, 16,16,16,17,18,20,24,25, 16,16,17,18,20,24,25,28, 16,17,18,20,24,25,28,33, 17,18,20,24,25,28,33,41, 18,20,24,25,28,33,41,54, 20,24,25,28,33,41,54,71, 24,25,28,33,41,54,71,91 }; const UInt g_scalingListSize [SCALING_LIST_SIZE_NUM] = {16,64,256,1024}; const UInt g_scalingListSizeX [SCALING_LIST_SIZE_NUM] = { 4, 8, 16, 32}; //! \} HM-HM-18.0/source/Lib/TLibCommon/TComRom.h000066400000000000000000000205701442026013100177470ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComRom.h \brief global variables & functions (header) */ #ifndef __TCOMROM__ #define __TCOMROM__ #include "CommonDef.h" #include #include //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Initialize / destroy functions // ==================================================================================================================== Void initROM(); Void destroyROM(); // ==================================================================================================================== // Data structure related table & variable // ==================================================================================================================== // flexible conversion from relative to absolute index extern UInt g_auiZscanToRaster[ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ]; extern UInt g_auiRasterToZscan[ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ]; extern UInt* g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][ MAX_CU_DEPTH ][ MAX_CU_DEPTH ]; Void initZscanToRaster ( Int iMaxDepth, Int iDepth, UInt uiStartVal, UInt*& rpuiCurrIdx ); Void initRasterToZscan ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth ); // conversion of partition index to picture pel position extern UInt g_auiRasterToPelX[ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ]; extern UInt g_auiRasterToPelY[ MAX_NUM_PART_IDXS_IN_CTU_WIDTH*MAX_NUM_PART_IDXS_IN_CTU_WIDTH ]; Void initRasterToPelXY ( UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxDepth ); extern const UInt g_auiPUOffset[NUMBER_OF_PART_SIZES]; extern const Int g_quantScales[SCALING_LIST_REM_NUM]; // Q(QP%6) extern const Int g_invQuantScales[SCALING_LIST_REM_NUM]; // IQ(QP%6) #if RExt__HIGH_PRECISION_FORWARD_TRANSFORM static const Int g_transformMatrixShift[TRANSFORM_NUMBER_OF_DIRECTIONS] = { 14, 6 }; #else static const Int g_transformMatrixShift[TRANSFORM_NUMBER_OF_DIRECTIONS] = { 6, 6 }; #endif extern const TMatrixCoeff g_aiT4 [TRANSFORM_NUMBER_OF_DIRECTIONS][4][4]; extern const TMatrixCoeff g_aiT8 [TRANSFORM_NUMBER_OF_DIRECTIONS][8][8]; extern const TMatrixCoeff g_aiT16[TRANSFORM_NUMBER_OF_DIRECTIONS][16][16]; extern const TMatrixCoeff g_aiT32[TRANSFORM_NUMBER_OF_DIRECTIONS][32][32]; #if JVET_X0048_X0103_FILM_GRAIN extern const TMatrixCoeff g_aiT64[TRANSFORM_NUMBER_OF_DIRECTIONS][64][64]; extern const TMatrixCoeff T64_DCT[64][64]; #endif // ==================================================================================================================== // Luma QP to Chroma QP mapping // ==================================================================================================================== static const Int chromaQPMappingTableSize = 58; extern const UChar g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize]; // ==================================================================================================================== // Scanning order & context mapping table // ==================================================================================================================== extern const UInt ctxIndMap4x4[4*4]; extern const UInt g_uiGroupIdx[ MAX_TU_SIZE ]; extern const UInt g_uiMinInGroup[ LAST_SIGNIFICANT_GROUPS ]; // ==================================================================================================================== // Intra prediction table // ==================================================================================================================== extern const UChar g_aucIntraModeNumFast_UseMPM[MAX_CU_DEPTH]; extern const UChar g_aucIntraModeNumFast_NotUseMPM[MAX_CU_DEPTH]; extern const UChar g_chroma422IntraAngleMappingTable[NUM_INTRA_MODE]; // ==================================================================================================================== // Mode-Dependent DST Matrices // ==================================================================================================================== extern const TMatrixCoeff g_as_DST_MAT_4 [TRANSFORM_NUMBER_OF_DIRECTIONS][4][4]; // ==================================================================================================================== // Misc. // ==================================================================================================================== extern SChar g_aucConvertToBit [ MAX_CU_SIZE+1 ]; // from width to log2(width)-2 #if ENC_DEC_TRACE extern FILE* g_hTrace; extern Bool g_bJustDoIt; extern const Bool g_bEncDecTraceEnable; extern const Bool g_bEncDecTraceDisable; extern Bool g_HLSTraceEnable; extern UInt64 g_nSymbolCounter; #define COUNTER_START 1 #define COUNTER_END 0 //( UInt64(1) << 63 ) #define DTRACE_CABAC_F(x) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%f", x ); #define DTRACE_CABAC_V(x) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%d", x ); #define DTRACE_CABAC_VL(x) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%lld", x ); #define DTRACE_CABAC_T(x) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%s", x ); #define DTRACE_CABAC_X(x) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "%x", x ); #define DTRACE_CABAC_R( x,y ) if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, x, y ); #define DTRACE_CABAC_N if ( ( g_nSymbolCounter >= COUNTER_START && g_nSymbolCounter <= COUNTER_END )|| g_bJustDoIt ) fprintf( g_hTrace, "\n" ); #else #define DTRACE_CABAC_F(x) #define DTRACE_CABAC_V(x) #define DTRACE_CABAC_VL(x) #define DTRACE_CABAC_T(x) #define DTRACE_CABAC_X(x) #define DTRACE_CABAC_R( x,y ) #define DTRACE_CABAC_N #endif const TChar* nalUnitTypeToString(NalUnitType type); extern const TChar *MatrixType[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; extern const TChar *MatrixType_DC[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; extern const Int g_quantTSDefault4x4[4*4]; extern const Int g_quantIntraDefault8x8[8*8]; extern const Int g_quantInterDefault8x8[8*8]; extern const UInt g_scalingListSize [SCALING_LIST_SIZE_NUM]; extern const UInt g_scalingListSizeX[SCALING_LIST_SIZE_NUM]; //! \} #endif //__TCOMROM__ HM-HM-18.0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp000066400000000000000000000532141442026013100236140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComSampleAdaptiveOffset.cpp \brief sample adaptive offset class */ #include "TComSampleAdaptiveOffset.h" #include #include #include #include //! \ingroup TLibCommon //! \{ SAOOffset::SAOOffset() { reset(); } SAOOffset::~SAOOffset() { } Void SAOOffset::reset() { modeIdc = SAO_MODE_OFF; typeIdc = -1; typeAuxInfo = -1; ::memset(offset, 0, sizeof(Int)* MAX_NUM_SAO_CLASSES); } const SAOOffset& SAOOffset::operator= (const SAOOffset& src) { modeIdc = src.modeIdc; typeIdc = src.typeIdc; typeAuxInfo = src.typeAuxInfo; ::memcpy(offset, src.offset, sizeof(Int)* MAX_NUM_SAO_CLASSES); return *this; } SAOBlkParam::SAOBlkParam() { reset(); } SAOBlkParam::~SAOBlkParam() { } Void SAOBlkParam::reset() { for(Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { offsetParam[compIdx].reset(); } } const SAOBlkParam& SAOBlkParam::operator= (const SAOBlkParam& src) { for(Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { offsetParam[compIdx] = src.offsetParam[compIdx]; } return *this; } TComSampleAdaptiveOffset::TComSampleAdaptiveOffset() { m_tempPicYuv = NULL; m_lineBufWidth = 0; m_signLineBuf1 = NULL; m_signLineBuf2 = NULL; } TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset() { destroy(); if (m_signLineBuf1) { delete[] m_signLineBuf1; m_signLineBuf1 = NULL; } if (m_signLineBuf2) { delete[] m_signLineBuf2; m_signLineBuf2 = NULL; } } Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, ChromaFormat format, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth, UInt lumaBitShift, UInt chromaBitShift ) { destroy(); m_picWidth = picWidth; m_picHeight = picHeight; m_chromaFormatIDC = format; m_maxCUWidth = maxCUWidth; m_maxCUHeight = maxCUHeight; m_numCTUInWidth = (m_picWidth/m_maxCUWidth) + ((m_picWidth % m_maxCUWidth)?1:0); m_numCTUInHeight = (m_picHeight/m_maxCUHeight) + ((m_picHeight % m_maxCUHeight)?1:0); m_numCTUsPic = m_numCTUInHeight*m_numCTUInWidth; //temporary picture buffer if ( !m_tempPicYuv ) { m_tempPicYuv = new TComPicYuv; m_tempPicYuv->create( m_picWidth, m_picHeight, m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, maxCUDepth, true ); } //bit-depth related for(Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { m_offsetStepLog2 [compIdx] = isLuma(ComponentID(compIdx))? lumaBitShift : chromaBitShift; } } Void TComSampleAdaptiveOffset::destroy() { if ( m_tempPicYuv ) { m_tempPicYuv->destroy(); delete m_tempPicYuv; m_tempPicYuv = NULL; } } Void TComSampleAdaptiveOffset::invertQuantOffsets(ComponentID compIdx, Int typeIdc, Int typeAuxInfo, Int* dstOffsets, Int* srcOffsets) { Int codedOffset[MAX_NUM_SAO_CLASSES]; ::memcpy(codedOffset, srcOffsets, sizeof(Int)*MAX_NUM_SAO_CLASSES); ::memset(dstOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES); if(typeIdc == SAO_TYPE_START_BO) { for(Int i=0; i< 4; i++) { dstOffsets[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES] = codedOffset[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES]*(1< 0) { mergedCTUPos = ctuRsAddr- m_numCTUInWidth; if( pic->getSAOMergeAvailability(ctuRsAddr, mergedCTUPos) ) { mergeCandidate = &(blkParams[mergedCTUPos]); } } } break; case SAO_MERGE_LEFT: { if(ctuX > 0) { mergedCTUPos = ctuRsAddr- 1; if( pic->getSAOMergeAvailability(ctuRsAddr, mergedCTUPos) ) { mergeCandidate = &(blkParams[mergedCTUPos]); } } } break; default: { printf("not a supported merge type"); assert(0); exit(-1); } } mergeList[mergeType]=mergeCandidate; if (mergeCandidate != NULL) { numValidMergeCandidates++; } } return numValidMergeCandidates; } Void TComSampleAdaptiveOffset::reconstructBlkSAOParam(SAOBlkParam& recParam, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES]) { const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID component = ComponentID(compIdx); SAOOffset& offsetParam = recParam[component]; if(offsetParam.modeIdc == SAO_MODE_OFF) { continue; } switch(offsetParam.modeIdc) { case SAO_MODE_NEW: { invertQuantOffsets(component, offsetParam.typeIdc, offsetParam.typeAuxInfo, offsetParam.offset, offsetParam.offset); } break; case SAO_MODE_MERGE: { SAOBlkParam* mergeTarget = mergeList[offsetParam.typeIdc]; assert(mergeTarget != NULL); offsetParam = (*mergeTarget)[component]; } break; default: { printf("Not a supported mode"); assert(0); exit(-1); } } } } Void TComSampleAdaptiveOffset::reconstructBlkSAOParams(TComPic* pic, SAOBlkParam* saoBlkParams) { for(Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { m_picSAOEnabled[compIdx] = false; } const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++) { SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES] = { NULL }; getMergeList(pic, ctuRsAddr, saoBlkParams, mergeList); reconstructBlkSAOParam(saoBlkParams[ctuRsAddr], mergeList); for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { if(saoBlkParams[ctuRsAddr][compIdx].modeIdc != SAO_MODE_OFF) { m_picSAOEnabled[compIdx] = true; } } } } Void TComSampleAdaptiveOffset::offsetBlock(const Int channelBitDepth, Int typeIdx, Int* offset , Pel* srcBlk, Pel* resBlk, Int srcStride, Int resStride, Int width, Int height , Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail) { if(m_lineBufWidth != m_maxCUWidth) { m_lineBufWidth = m_maxCUWidth; if (m_signLineBuf1) { delete[] m_signLineBuf1; m_signLineBuf1 = NULL; } m_signLineBuf1 = new SChar[m_lineBufWidth+1]; if (m_signLineBuf2) { delete[] m_signLineBuf2; m_signLineBuf2 = NULL; } m_signLineBuf2 = new SChar[m_lineBufWidth+1]; } const Int maxSampleValueIncl = (1<< channelBitDepth )-1; Int x,y, startX, startY, endX, endY, edgeType; Int firstLineStartX, firstLineEndX, lastLineStartX, lastLineEndX; SChar signLeft, signRight, signDown; Pel* srcLine = srcBlk; Pel* resLine = resBlk; switch(typeIdx) { case SAO_TYPE_EO_0: { offset += 2; startX = isLeftAvail ? 0 : 1; endX = isRightAvail ? width : (width -1); for (y=0; y< height; y++) { signLeft = (SChar)sgn(srcLine[startX] - srcLine[startX-1]); for (x=startX; x< endX; x++) { signRight = (SChar)sgn(srcLine[x] - srcLine[x+1]); edgeType = signRight + signLeft; signLeft = -signRight; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } srcLine += srcStride; resLine += resStride; } } break; case SAO_TYPE_EO_90: { offset += 2; SChar *signUpLine = m_signLineBuf1; startY = isAboveAvail ? 0 : 1; endY = isBelowAvail ? height : height-1; if (!isAboveAvail) { srcLine += srcStride; resLine += resStride; } Pel* srcLineAbove= srcLine- srcStride; for (x=0; x< width; x++) { signUpLine[x] = (SChar)sgn(srcLine[x] - srcLineAbove[x]); } Pel* srcLineBelow; for (y=startY; y(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } srcLine += srcStride; resLine += resStride; } } break; case SAO_TYPE_EO_135: { offset += 2; SChar *signUpLine, *signDownLine, *signTmpLine; signUpLine = m_signLineBuf1; signDownLine= m_signLineBuf2; startX = isLeftAvail ? 0 : 1 ; endX = isRightAvail ? width : (width-1); //prepare 2nd line's upper sign Pel* srcLineBelow= srcLine+ srcStride; for (x=startX; x< endX+1; x++) { signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x- 1]); } //1st line Pel* srcLineAbove= srcLine- srcStride; firstLineStartX = isAboveLeftAvail ? 0 : 1; firstLineEndX = isAboveAvail? endX: 1; for(x= firstLineStartX; x< firstLineEndX; x++) { edgeType = sgn(srcLine[x] - srcLineAbove[x- 1]) - signUpLine[x+1]; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } srcLine += srcStride; resLine += resStride; //middle lines for (y= 1; y< height-1; y++) { srcLineBelow= srcLine+ srcStride; for (x=startX; x(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); signDownLine[x+1] = -signDown; } signDownLine[startX] = (SChar)sgn(srcLineBelow[startX] - srcLine[startX-1]); signTmpLine = signUpLine; signUpLine = signDownLine; signDownLine = signTmpLine; srcLine += srcStride; resLine += resStride; } //last line srcLineBelow= srcLine+ srcStride; lastLineStartX = isBelowAvail ? startX : (width -1); lastLineEndX = isBelowRightAvail ? width : (width -1); for(x= lastLineStartX; x< lastLineEndX; x++) { edgeType = sgn(srcLine[x] - srcLineBelow[x+ 1]) + signUpLine[x]; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } } break; case SAO_TYPE_EO_45: { offset += 2; SChar *signUpLine = m_signLineBuf1+1; startX = isLeftAvail ? 0 : 1; endX = isRightAvail ? width : (width -1); //prepare 2nd line upper sign Pel* srcLineBelow= srcLine+ srcStride; for (x=startX-1; x< endX; x++) { signUpLine[x] = (SChar)sgn(srcLineBelow[x] - srcLine[x+1]); } //first line Pel* srcLineAbove= srcLine- srcStride; firstLineStartX = isAboveAvail ? startX : (width -1 ); firstLineEndX = isAboveRightAvail ? width : (width-1); for(x= firstLineStartX; x< firstLineEndX; x++) { edgeType = sgn(srcLine[x] - srcLineAbove[x+1]) -signUpLine[x-1]; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } srcLine += srcStride; resLine += resStride; //middle lines for (y= 1; y< height-1; y++) { srcLineBelow= srcLine+ srcStride; for(x= startX; x< endX; x++) { signDown = (SChar)sgn(srcLine[x] - srcLineBelow[x-1]); edgeType = signDown + signUpLine[x]; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); signUpLine[x-1] = -signDown; } signUpLine[endX-1] = (SChar)sgn(srcLineBelow[endX-1] - srcLine[endX]); srcLine += srcStride; resLine += resStride; } //last line srcLineBelow= srcLine+ srcStride; lastLineStartX = isBelowLeftAvail ? 0 : 1; lastLineEndX = isBelowAvail ? endX : 1; for(x= lastLineStartX; x< lastLineEndX; x++) { edgeType = sgn(srcLine[x] - srcLineBelow[x-1]) + signUpLine[x]; resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[edgeType]); } } break; case SAO_TYPE_BO: { const Int shiftBits = channelBitDepth - NUM_SAO_BO_CLASSES_LOG2; for (y=0; y< height; y++) { for (x=0; x< width; x++) { resLine[x] = Clip3(0, maxSampleValueIncl, srcLine[x] + offset[srcLine[x] >> shiftBits] ); } srcLine += srcStride; resLine += resStride; } } break; default: { printf("Not a supported SAO types\n"); assert(0); exit(-1); } } } Void TComSampleAdaptiveOffset::offsetCTU(Int ctuRsAddr, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic) { Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail; const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); Bool bAllOff=true; for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { if (saoblkParam[compIdx].modeIdc != SAO_MODE_OFF) { bAllOff=false; } } if (bAllOff) { return; } //block boundary availability pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctuRsAddr, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail); Int yPos = (ctuRsAddr / m_numCTUInWidth)*m_maxCUHeight; Int xPos = (ctuRsAddr % m_numCTUInWidth)*m_maxCUWidth; Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight; Int width = (xPos + m_maxCUWidth > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth; for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID component = ComponentID(compIdx); SAOOffset& ctbOffset = saoblkParam[compIdx]; if(ctbOffset.modeIdc != SAO_MODE_OFF) { const UInt componentScaleX = getComponentScaleX(component, pPic->getChromaFormat()); const UInt componentScaleY = getComponentScaleY(component, pPic->getChromaFormat()); Int blkWidth = (width >> componentScaleX); Int blkHeight = (height >> componentScaleY); Int blkXPos = (xPos >> componentScaleX); Int blkYPos = (yPos >> componentScaleY); Int srcStride = srcYuv->getStride(component); Pel* srcBlk = srcYuv->getAddr(component) + blkYPos*srcStride + blkXPos; Int resStride = resYuv->getStride(component); Pel* resBlk = resYuv->getAddr(component) + blkYPos*resStride + blkXPos; offsetBlock( pPic->getPicSym()->getSPS().getBitDepth(toChannelType(component)), ctbOffset.typeIdc, ctbOffset.offset , srcBlk, resBlk, srcStride, resStride, blkWidth, blkHeight , isLeftAvail, isRightAvail , isAboveAvail, isBelowAvail , isAboveLeftAvail, isAboveRightAvail , isBelowLeftAvail, isBelowRightAvail ); } } //compIdx } Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pDecPic) { const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); Bool bAllDisabled=true; for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { if (m_picSAOEnabled[compIdx]) { bAllDisabled=false; } } if (bAllDisabled) { return; } TComPicYuv* resYuv = pDecPic->getPicYuvRec(); TComPicYuv* srcYuv = m_tempPicYuv; resYuv->copyToPic(srcYuv); for(Int ctuRsAddr= 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++) { offsetCTU(ctuRsAddr, srcYuv, resYuv, (pDecPic->getPicSym()->getSAOBlkParam())[ctuRsAddr], pDecPic); } //ctu } /** PCM LF disable process. * \param pcPic picture (TComPic) pointer * * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones. */ Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic) { xPCMRestoration(pcPic); } /** Picture-level PCM restoration. * \param pcPic picture (TComPic) pointer */ Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic) { Bool bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false; if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnabledFlag()) { for( UInt ctuRsAddr = 0; ctuRsAddr < pcPic->getNumberOfCtusInFrame() ; ctuRsAddr++ ) { TComDataCU* pcCU = pcPic->getCtu(ctuRsAddr); xPCMCURestoration(pcCU, 0, 0); } } } /** PCM CU restoration. * \param pcCU pointer to current CU * \param uiAbsZorderIdx part index * \param uiDepth CU depth */ Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth ) { TComPic* pcPic = pcCU->getPic(); UInt uiCurNumParts = pcPic->getNumPartitionsInCtu() >> (uiDepth<<1); UInt uiQNumParts = uiCurNumParts>>2; // go to sub-CU if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth ) { for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts ) { UInt uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ]; UInt uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ]; if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) ) { xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 ); } } return; } // restore PCM samples if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx)) { const UInt numComponents=pcPic->getNumberValidComponents(); for(UInt comp=0; compgetPic()->getPicYuvRec(); UInt uiPcmLeftShiftBit; const UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight(); const UInt csx=pcPicYuvRec->getComponentScaleX(compID); const UInt csy=pcPicYuvRec->getComponentScaleY(compID); const UInt uiOffset = (uiMinCoeffSize*uiAbsZorderIdx)>>(csx+csy); Pel *piSrc = pcPicYuvRec->getAddr(compID, pcCU->getCtuRsAddr(), uiAbsZorderIdx); const Pel *piPcm = pcCU->getPCMSample(compID) + uiOffset; const UInt uiStride = pcPicYuvRec->getStride(compID); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiWidth = ((sps.getMaxCUWidth() >> uiDepth) >> csx); const UInt uiHeight = ((sps.getMaxCUHeight() >> uiDepth) >> csy); if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) ) { uiPcmLeftShiftBit = 0; } else { uiPcmLeftShiftBit = sps.getBitDepth(toChannelType(compID)) - sps.getPCMBitDepth(toChannelType(compID)); } for(UInt uiY = 0; uiY < uiHeight; uiY++ ) { for(UInt uiX = 0; uiX < uiWidth; uiX++ ) { piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit); } piPcm += uiWidth; piSrc += uiStride; } } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.h000066400000000000000000000112751442026013100232620ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComSampleAdaptiveOffset.h \brief sample adaptive offset class (header) */ #ifndef __TCOMSAMPLEADAPTIVEOFFSET__ #define __TCOMSAMPLEADAPTIVEOFFSET__ #include "CommonDef.h" #include "TComPic.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constants // ==================================================================================================================== #define MAX_SAO_TRUNCATED_BITDEPTH 10 // ==================================================================================================================== // Class definition // ==================================================================================================================== template Int sgn(T val) { return (T(0) < val) - (val < T(0)); } class TComSampleAdaptiveOffset { public: TComSampleAdaptiveOffset(); virtual ~TComSampleAdaptiveOffset(); Void SAOProcess(TComPic* pDecPic); Void create( Int picWidth, Int picHeight, ChromaFormat format, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth, UInt lumaBitShift, UInt chromaBitShift ); Void destroy(); Void reconstructBlkSAOParams(TComPic* pic, SAOBlkParam* saoBlkParams); Void PCMLFDisableProcess (TComPic* pcPic); static Int getMaxOffsetQVal(const Int channelBitDepth) { return (1<<(std::min(channelBitDepth,MAX_SAO_TRUNCATED_BITDEPTH)-5))-1; } //Table 9-32, inclusive protected: Void offsetBlock(const Int channelBitDepth, Int typeIdx, Int* offset, Pel* srcBlk, Pel* resBlk, Int srcStride, Int resStride, Int width, Int height , Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail); Void invertQuantOffsets(ComponentID compIdx, Int typeIdc, Int typeAuxInfo, Int* dstOffsets, Int* srcOffsets); Void reconstructBlkSAOParam(SAOBlkParam& recParam, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES]); Int getMergeList(TComPic* pic, Int ctuRsAddr, SAOBlkParam* blkParams, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES]); Void offsetCTU(Int ctuRsAddr, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic); Void xPCMRestoration(TComPic* pcPic); Void xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth ); Void xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, const ComponentID compID); protected: UInt m_offsetStepLog2[MAX_NUM_COMPONENT]; //offset step TComPicYuv* m_tempPicYuv; //temporary buffer Int m_picWidth; Int m_picHeight; Int m_maxCUWidth; Int m_maxCUHeight; Int m_numCTUInWidth; Int m_numCTUInHeight; Int m_numCTUsPic; Int m_lineBufWidth; SChar* m_signLineBuf1; SChar* m_signLineBuf2; ChromaFormat m_chromaFormatIDC; private: Bool m_picSAOEnabled[MAX_NUM_COMPONENT]; }; //! \} #endif HM-HM-18.0/source/Lib/TLibCommon/TComSlice.cpp000066400000000000000000002216571442026013100206150ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComSlice.cpp \brief slice header and SPS class */ #include "CommonDef.h" #include "TComSlice.h" #include "TComPic.h" #include "TLibEncoder/TEncSbac.h" #include "TLibDecoder/TDecSbac.h" //! \ingroup TLibCommon //! \{ TComSlice::TComSlice() : m_iPPSId ( -1 ) , m_PicOutputFlag ( true ) , m_iPOC ( 0 ) , m_iLastIDR ( 0 ) , m_iAssociatedIRAP ( 0 ) , m_iAssociatedIRAPType ( NAL_UNIT_INVALID ) , m_pRPS ( 0 ) , m_localRPS ( ) , m_rpsIdx ( 0 ) , m_RefPicListModification ( ) , m_eNalUnitType ( NAL_UNIT_CODED_SLICE_IDR_W_RADL ) , m_eSliceType ( I_SLICE ) , m_iSliceQp ( 0 ) , m_dependentSliceSegmentFlag ( false ) #if ADAPTIVE_QP_SELECTION , m_iSliceQpBase ( 0 ) #endif , m_ChromaQpAdjEnabled ( false ) , m_deblockingFilterDisable ( false ) , m_deblockingFilterOverrideFlag ( false ) , m_deblockingFilterBetaOffsetDiv2( 0 ) , m_deblockingFilterTcOffsetDiv2 ( 0 ) , m_bCheckLDC ( false ) , m_iSliceQpDelta ( 0 ) , m_iDepth ( 0 ) , m_bRefenced ( false ) , m_pcVPS ( NULL ) , m_pcSPS ( NULL ) , m_pcPPS ( NULL ) , m_pcPic ( NULL ) , m_colFromL0Flag ( true ) , m_noOutputPriorPicsFlag ( false ) , m_noRaslOutputFlag ( false ) , m_handleCraAsBlaFlag ( false ) , m_colRefIdx ( 0 ) , m_maxNumMergeCand ( 0 ) , m_uiTLayer ( 0 ) , m_bTLayerSwitchingFlag ( false ) , m_sliceMode ( NO_SLICES ) , m_sliceArgument ( 0 ) , m_sliceCurStartCtuTsAddr ( 0 ) , m_sliceCurEndCtuTsAddr ( 0 ) , m_sliceIdx ( 0 ) , m_sliceSegmentMode ( NO_SLICES ) , m_sliceSegmentArgument ( 0 ) , m_sliceSegmentCurStartCtuTsAddr ( 0 ) , m_sliceSegmentCurEndCtuTsAddr ( 0 ) , m_nextSlice ( false ) , m_nextSliceSegment ( false ) , m_sliceBits ( 0 ) , m_sliceSegmentBits ( 0 ) , m_bFinalized ( false ) , m_bTestWeightPred ( false ) , m_bTestWeightBiPred ( false ) , m_substreamSizes ( ) , m_cabacInitFlag ( false ) , m_bLMvdL1Zero ( false ) , m_temporalLayerNonReferenceFlag ( false ) , m_LFCrossSliceBoundaryFlag ( false ) , m_enableTMVPFlag ( true ) , m_encCABACTableIdx (I_SLICE) { for(UInt i=0; i& rcListPic) { TComPic* pcPicExtract; TComPic* pcPicInsert; TComList::iterator iterPicExtract; TComList::iterator iterPicExtract_1; TComList::iterator iterPicInsert; for (Int i = 1; i < (Int)(rcListPic.size()); i++) { iterPicExtract = rcListPic.begin(); for (Int j = 0; j < i; j++) { iterPicExtract++; } pcPicExtract = *(iterPicExtract); pcPicExtract->setCurrSliceIdx(0); iterPicInsert = rcListPic.begin(); while (iterPicInsert != iterPicExtract) { pcPicInsert = *(iterPicInsert); pcPicInsert->setCurrSliceIdx(0); if (pcPicInsert->getPOC() >= pcPicExtract->getPOC()) { break; } iterPicInsert++; } iterPicExtract_1 = iterPicExtract; iterPicExtract_1++; // swap iterPicExtract and iterPicInsert, iterPicExtract = curr. / iterPicInsert = insertion position rcListPic.insert (iterPicInsert, iterPicExtract, iterPicExtract_1); rcListPic.erase (iterPicExtract); } } TComPic* TComSlice::xGetRefPic (TComList& rcListPic, Int poc) { TComList::iterator iterPic = rcListPic.begin(); TComPic* pcPic = *(iterPic); while ( iterPic != rcListPic.end() ) { if(pcPic->getPOC() == poc) { break; } iterPic++; pcPic = *(iterPic); } return pcPic; } TComPic* TComSlice::xGetLongTermRefPic(TComList& rcListPic, Int poc, Bool pocHasMsb) { TComList::iterator iterPic = rcListPic.begin(); TComPic* pcPic = *(iterPic); TComPic* pcStPic = pcPic; Int pocCycle = 1 << getSPS()->getBitsForPOC(); if (!pocHasMsb) { poc = poc & (pocCycle - 1); } while ( iterPic != rcListPic.end() ) { pcPic = *(iterPic); if (pcPic && pcPic->getPOC()!=this->getPOC() && pcPic->getSlice( 0 )->isReferenced()) { Int picPoc = pcPic->getPOC(); if (!pocHasMsb) { picPoc = picPoc & (pocCycle - 1); } if (poc == picPoc) { if(pcPic->getIsLongTerm()) { return pcPic; } else { pcStPic = pcPic; } break; } } iterPic++; } return pcStPic; } Void TComSlice::setRefPOCList () { for (Int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++) { for (Int iNumRefIdx = 0; iNumRefIdx < m_aiNumRefIdx[iDir]; iNumRefIdx++) { m_aiRefPOCList[iDir][iNumRefIdx] = m_apcRefPicList[iDir][iNumRefIdx]->getPOC(); } } } Void TComSlice::setList1IdxToList0Idx() { Int idxL0, idxL1; for ( idxL1 = 0; idxL1 < getNumRefIdx( REF_PIC_LIST_1 ); idxL1++ ) { m_list1IdxToList0Idx[idxL1] = -1; for ( idxL0 = 0; idxL0 < getNumRefIdx( REF_PIC_LIST_0 ); idxL0++ ) { if ( m_apcRefPicList[REF_PIC_LIST_0][idxL0]->getPOC() == m_apcRefPicList[REF_PIC_LIST_1][idxL1]->getPOC() ) { m_list1IdxToList0Idx[idxL1] = idxL0; break; } } } } Void TComSlice::setRefPicList( TComList& rcListPic, Bool checkNumPocTotalCurr ) { if ( m_eSliceType == I_SLICE) { ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList)); ::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx )); if (!checkNumPocTotalCurr) { return; } } TComPic* pcRefPic= NULL; static const UInt MAX_NUM_NEGATIVE_PICTURES=16; TComPic* RefPicSetStCurr0[MAX_NUM_NEGATIVE_PICTURES]; TComPic* RefPicSetStCurr1[MAX_NUM_NEGATIVE_PICTURES]; TComPic* RefPicSetLtCurr[MAX_NUM_NEGATIVE_PICTURES]; UInt NumPicStCurr0 = 0; UInt NumPicStCurr1 = 0; UInt NumPicLtCurr = 0; Int i; for(i=0; i < m_pRPS->getNumberOfNegativePictures(); i++) { if(m_pRPS->getUsed(i)) { pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pRPS->getDeltaPOC(i)); pcRefPic->setIsLongTerm(0); pcRefPic->getPicYuvRec()->extendPicBorder(); RefPicSetStCurr0[NumPicStCurr0] = pcRefPic; NumPicStCurr0++; pcRefPic->setCheckLTMSBPresent(false); } } for(; i < m_pRPS->getNumberOfNegativePictures()+m_pRPS->getNumberOfPositivePictures(); i++) { if(m_pRPS->getUsed(i)) { pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pRPS->getDeltaPOC(i)); pcRefPic->setIsLongTerm(0); pcRefPic->getPicYuvRec()->extendPicBorder(); RefPicSetStCurr1[NumPicStCurr1] = pcRefPic; NumPicStCurr1++; pcRefPic->setCheckLTMSBPresent(false); } } for(i = m_pRPS->getNumberOfNegativePictures()+m_pRPS->getNumberOfPositivePictures()+m_pRPS->getNumberOfLongtermPictures()-1; i > m_pRPS->getNumberOfNegativePictures()+m_pRPS->getNumberOfPositivePictures()-1 ; i--) { if(m_pRPS->getUsed(i)) { pcRefPic = xGetLongTermRefPic(rcListPic, m_pRPS->getPOC(i), m_pRPS->getCheckLTMSBPresent(i)); pcRefPic->setIsLongTerm(1); pcRefPic->getPicYuvRec()->extendPicBorder(); RefPicSetLtCurr[NumPicLtCurr] = pcRefPic; NumPicLtCurr++; } if(pcRefPic==NULL) { pcRefPic = xGetLongTermRefPic(rcListPic, m_pRPS->getPOC(i), m_pRPS->getCheckLTMSBPresent(i)); } pcRefPic->setCheckLTMSBPresent(m_pRPS->getCheckLTMSBPresent(i)); } // ref_pic_list_init TComPic* rpsCurrList0[MAX_NUM_REF+1]; TComPic* rpsCurrList1[MAX_NUM_REF+1]; Int numPicTotalCurr = NumPicStCurr0 + NumPicStCurr1 + NumPicLtCurr; if (checkNumPocTotalCurr) { // The variable NumPocTotalCurr is derived as specified in subclause 7.4.7.2. It is a requirement of bitstream conformance that the following applies to the value of NumPocTotalCurr: // - If the current picture is a BLA or CRA picture, the value of NumPocTotalCurr shall be equal to 0. // - Otherwise, when the current picture contains a P or B slice, the value of NumPocTotalCurr shall not be equal to 0. if (getRapPicFlag()) { assert(numPicTotalCurr == 0); } if (m_eSliceType == I_SLICE) { return; } assert(numPicTotalCurr > 0); // general tier and level limit: assert(numPicTotalCurr <= 8); } Int cIdx = 0; for ( i=0; i= 0 && cIdx < numPicTotalCurr); m_apcRefPicList[REF_PIC_LIST_0][rIdx] = rpsCurrList0[ cIdx ]; m_bIsUsedAsLongTerm[REF_PIC_LIST_0][rIdx] = ( cIdx >= NumPicStCurr0 + NumPicStCurr1 ); } if ( m_eSliceType != B_SLICE ) { m_aiNumRefIdx[REF_PIC_LIST_1] = 0; ::memset( m_apcRefPicList[REF_PIC_LIST_1], 0, sizeof(m_apcRefPicList[REF_PIC_LIST_1])); } else { for (Int rIdx = 0; rIdx < m_aiNumRefIdx[REF_PIC_LIST_1]; rIdx ++) { cIdx = m_RefPicListModification.getRefPicListModificationFlagL1() ? m_RefPicListModification.getRefPicSetIdxL1(rIdx) : rIdx % numPicTotalCurr; assert(cIdx >= 0 && cIdx < numPicTotalCurr); m_apcRefPicList[REF_PIC_LIST_1][rIdx] = rpsCurrList1[ cIdx ]; m_bIsUsedAsLongTerm[REF_PIC_LIST_1][rIdx] = ( cIdx >= NumPicStCurr0 + NumPicStCurr1 ); } } } Int TComSlice::getNumRpsCurrTempList() const { Int numRpsCurrTempList = 0; if (m_eSliceType == I_SLICE) { return 0; } for(UInt i=0; i < m_pRPS->getNumberOfNegativePictures()+ m_pRPS->getNumberOfPositivePictures() + m_pRPS->getNumberOfLongtermPictures(); i++) { if(m_pRPS->getUsed(i)) { numRpsCurrTempList++; } } return numRpsCurrTempList; } Void TComSlice::initEqualRef() { for (Int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++) { for (Int iRefIdx1 = 0; iRefIdx1 < MAX_NUM_REF; iRefIdx1++) { for (Int iRefIdx2 = iRefIdx1; iRefIdx2 < MAX_NUM_REF; iRefIdx2++) { m_abEqualRef[iDir][iRefIdx1][iRefIdx2] = m_abEqualRef[iDir][iRefIdx2][iRefIdx1] = (iRefIdx1 == iRefIdx2? true : false); } } } } Void TComSlice::checkColRefIdx(UInt curSliceIdx, TComPic* pic) { Int i; TComSlice* curSlice = pic->getSlice(curSliceIdx); Int currColRefPOC = curSlice->getRefPOC( RefPicList(1 - curSlice->getColFromL0Flag()), curSlice->getColRefIdx()); TComSlice* preSlice; Int preColRefPOC; for(i=curSliceIdx-1; i>=0; i--) { preSlice = pic->getSlice(i); if(preSlice->getSliceType() != I_SLICE) { preColRefPOC = preSlice->getRefPOC( RefPicList(1 - preSlice->getColFromL0Flag()), preSlice->getColRefIdx()); if(currColRefPOC != preColRefPOC) { printf("Collocated_ref_idx shall always be the same for all slices of a coded picture!\n"); exit(EXIT_FAILURE); } else { break; } } } } Void TComSlice::checkCRA(const TComReferencePictureSet *pReferencePictureSet, Int& pocCRA, NalUnitType& associatedIRAPType, TComList& rcListPic) { for(Int i = 0; i < pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures(); i++) { if(pocCRA < MAX_UINT && getPOC() > pocCRA) { assert(getPOC()+pReferencePictureSet->getDeltaPOC(i) >= pocCRA); } } for(Int i = pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures(); i < pReferencePictureSet->getNumberOfPictures(); i++) { if(pocCRA < MAX_UINT && getPOC() > pocCRA) { if (!pReferencePictureSet->getCheckLTMSBPresent(i)) { assert(xGetLongTermRefPic(rcListPic, pReferencePictureSet->getPOC(i), false)->getPOC() >= pocCRA); } else { assert(pReferencePictureSet->getPOC(i) >= pocCRA); } } } if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) // IDR picture found { pocCRA = getPOC(); associatedIRAPType = getNalUnitType(); } else if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // CRA picture found { pocCRA = getPOC(); associatedIRAPType = getNalUnitType(); } else if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) // BLA picture found { pocCRA = getPOC(); associatedIRAPType = getNalUnitType(); } } /** Function for marking the reference pictures when an IDR/CRA/CRANT/BLA/BLANT is encountered. * \param pocCRA POC of the CRA/CRANT/BLA/BLANT picture * \param bRefreshPending flag indicating if a deferred decoding refresh is pending * \param rcListPic reference to the reference picture list * This function marks the reference pictures as "unused for reference" in the following conditions. * If the nal_unit_type is IDR/BLA/BLANT, all pictures in the reference picture list * are marked as "unused for reference" * If the nal_unit_type is BLA/BLANT, set the pocCRA to the temporal reference of the current picture. * Otherwise * If the bRefreshPending flag is true (a deferred decoding refresh is pending) and the current * temporal reference is greater than the temporal reference of the latest CRA/CRANT/BLA/BLANT picture (pocCRA), * mark all reference pictures except the latest CRA/CRANT/BLA/BLANT picture as "unused for reference" and set * the bRefreshPending flag to false. * If the nal_unit_type is CRA/CRANT, set the bRefreshPending flag to true and pocCRA to the temporal * reference of the current picture. * Note that the current picture is already placed in the reference list and its marking is not changed. * If the current picture has a nal_ref_idc that is not 0, it will remain marked as "used for reference". */ Void TComSlice::decodingRefreshMarking(Int& pocCRA, Bool& bRefreshPending, TComList& rcListPic, const bool bEfficientFieldIRAPEnabled) { TComPic* rpcPic; Int pocCurr = getPOC(); if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) // IDR or BLA picture { // mark all pictures as not used for reference TComList::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); rpcPic->setCurrSliceIdx(0); if (rpcPic->getPOC() != pocCurr) { rpcPic->getSlice(0)->setReferenced(false); } iterPic++; } if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) { pocCRA = pocCurr; } if (bEfficientFieldIRAPEnabled) { bRefreshPending = true; } } else // CRA or No DR { if(bEfficientFieldIRAPEnabled && (getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL)) { if (bRefreshPending==true && pocCurr > m_iLastIDR) // IDR reference marking pending { TComList::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != m_iLastIDR) { rpcPic->getSlice(0)->setReferenced(false); } iterPic++; } bRefreshPending = false; } } else { if (bRefreshPending==true && pocCurr > pocCRA) // CRA reference marking pending { TComList::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != pocCRA) { rpcPic->getSlice(0)->setReferenced(false); } iterPic++; } bRefreshPending = false; } } if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // CRA picture found { bRefreshPending = true; pocCRA = pocCurr; } } } Void TComSlice::copySliceInfo(TComSlice *pSrc) { assert( pSrc != NULL ); Int i, j, k; m_iPOC = pSrc->m_iPOC; m_eNalUnitType = pSrc->m_eNalUnitType; m_eSliceType = pSrc->m_eSliceType; m_iSliceQp = pSrc->m_iSliceQp; #if ADAPTIVE_QP_SELECTION m_iSliceQpBase = pSrc->m_iSliceQpBase; #endif m_ChromaQpAdjEnabled = pSrc->m_ChromaQpAdjEnabled; m_deblockingFilterDisable = pSrc->m_deblockingFilterDisable; m_deblockingFilterOverrideFlag = pSrc->m_deblockingFilterOverrideFlag; m_deblockingFilterBetaOffsetDiv2 = pSrc->m_deblockingFilterBetaOffsetDiv2; m_deblockingFilterTcOffsetDiv2 = pSrc->m_deblockingFilterTcOffsetDiv2; for (i = 0; i < NUM_REF_PIC_LIST_01; i++) { m_aiNumRefIdx[i] = pSrc->m_aiNumRefIdx[i]; } for (i = 0; i < MAX_NUM_REF; i++) { m_list1IdxToList0Idx[i] = pSrc->m_list1IdxToList0Idx[i]; } m_bCheckLDC = pSrc->m_bCheckLDC; m_iSliceQpDelta = pSrc->m_iSliceQpDelta; for (UInt component = 0; component < MAX_NUM_COMPONENT; component++) { m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component]; } for (i = 0; i < NUM_REF_PIC_LIST_01; i++) { for (j = 0; j < MAX_NUM_REF; j++) { m_apcRefPicList[i][j] = pSrc->m_apcRefPicList[i][j]; m_aiRefPOCList[i][j] = pSrc->m_aiRefPOCList[i][j]; m_bIsUsedAsLongTerm[i][j] = pSrc->m_bIsUsedAsLongTerm[i][j]; } m_bIsUsedAsLongTerm[i][MAX_NUM_REF] = pSrc->m_bIsUsedAsLongTerm[i][MAX_NUM_REF]; } m_iDepth = pSrc->m_iDepth; // referenced slice m_bRefenced = pSrc->m_bRefenced; // access channel m_pRPS = pSrc->m_pRPS; m_iLastIDR = pSrc->m_iLastIDR; m_pcPic = pSrc->m_pcPic; m_colFromL0Flag = pSrc->m_colFromL0Flag; m_colRefIdx = pSrc->m_colRefIdx; setLambdas(pSrc->getLambdas()); for (i = 0; i < NUM_REF_PIC_LIST_01; i++) { for (j = 0; j < MAX_NUM_REF; j++) { for (k =0; k < MAX_NUM_REF; k++) { m_abEqualRef[i][j][k] = pSrc->m_abEqualRef[i][j][k]; } } } m_uiTLayer = pSrc->m_uiTLayer; m_bTLayerSwitchingFlag = pSrc->m_bTLayerSwitchingFlag; m_sliceMode = pSrc->m_sliceMode; m_sliceArgument = pSrc->m_sliceArgument; m_sliceCurStartCtuTsAddr = pSrc->m_sliceCurStartCtuTsAddr; m_sliceCurEndCtuTsAddr = pSrc->m_sliceCurEndCtuTsAddr; m_sliceIdx = pSrc->m_sliceIdx; m_sliceSegmentMode = pSrc->m_sliceSegmentMode; m_sliceSegmentArgument = pSrc->m_sliceSegmentArgument; m_sliceSegmentCurStartCtuTsAddr = pSrc->m_sliceSegmentCurStartCtuTsAddr; m_sliceSegmentCurEndCtuTsAddr = pSrc->m_sliceSegmentCurEndCtuTsAddr; m_nextSlice = pSrc->m_nextSlice; m_nextSliceSegment = pSrc->m_nextSliceSegment; for ( UInt e=0 ; em_weightPredTable[e][n], sizeof(WPScalingParam)*MAX_NUM_COMPONENT ); } } for( UInt ch = 0 ; ch < MAX_NUM_CHANNEL_TYPE; ch++) { m_saoEnabledFlag[ch] = pSrc->m_saoEnabledFlag[ch]; } m_cabacInitFlag = pSrc->m_cabacInitFlag; m_bLMvdL1Zero = pSrc->m_bLMvdL1Zero; m_LFCrossSliceBoundaryFlag = pSrc->m_LFCrossSliceBoundaryFlag; m_enableTMVPFlag = pSrc->m_enableTMVPFlag; m_maxNumMergeCand = pSrc->m_maxNumMergeCand; m_encCABACTableIdx = pSrc->m_encCABACTableIdx; } /** Function for setting the slice's temporal layer ID and corresponding temporal_layer_switching_point_flag. * \param uiTLayer Temporal layer ID of the current slice * The decoder calls this function to set temporal_layer_switching_point_flag for each temporal layer based on * the SPS's temporal_id_nesting_flag and the parsed PPS. Then, current slice's temporal layer ID and * temporal_layer_switching_point_flag is set accordingly. */ Void TComSlice::setTLayerInfo( UInt uiTLayer ) { m_uiTLayer = uiTLayer; } /** Function for checking if this is a switching-point */ Bool TComSlice::isTemporalLayerSwitchingPoint(TComList& rcListPic) { TComPic* rpcPic; // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(rpcPic->getSlice(0)->isReferenced() && rpcPic->getPOC() != getPOC()) { if(rpcPic->getTLayer() >= getTLayer()) { return false; } } } return true; } /** Function for checking if this is a STSA candidate */ Bool TComSlice::isStepwiseTemporalLayerSwitchingPointCandidate(TComList& rcListPic) { TComPic* rpcPic; TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(rpcPic->getSlice(0)->isReferenced() && (rpcPic->getUsedByCurr()==true) && rpcPic->getPOC() != getPOC()) { if(rpcPic->getTLayer() >= getTLayer()) { return false; } } } return true; } Void TComSlice::checkLeadingPictureRestrictions(TComList& rcListPic) { TComPic* rpcPic; Int nalUnitType = this->getNalUnitType(); // When a picture is a leading picture, it shall be a RADL or RASL picture. if(this->getAssociatedIRAPPOC() > this->getPOC()) { // Do not check IRAP pictures since they may get a POC lower than their associated IRAP if(nalUnitType < NAL_UNIT_CODED_SLICE_BLA_W_LP || nalUnitType > NAL_UNIT_RESERVED_IRAP_VCL23) { assert(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R); } } // When a picture is a trailing picture, it shall not be a RADL or RASL picture. if(this->getAssociatedIRAPPOC() < this->getPOC()) { assert(nalUnitType != NAL_UNIT_CODED_SLICE_RASL_N && nalUnitType != NAL_UNIT_CODED_SLICE_RASL_R && nalUnitType != NAL_UNIT_CODED_SLICE_RADL_N && nalUnitType != NAL_UNIT_CODED_SLICE_RADL_R); } // No RASL pictures shall be present in the bitstream that are associated // with a BLA picture having nal_unit_type equal to BLA_W_RADL or BLA_N_LP. if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) { assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_W_RADL && this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_N_LP); } // No RASL pictures shall be present in the bitstream that are associated with // an IDR picture. if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) { assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_N_LP && this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_W_RADL); } // No RADL pictures shall be present in the bitstream that are associated with // a BLA picture having nal_unit_type equal to BLA_N_LP or that are associated // with an IDR picture having nal_unit_type equal to IDR_N_LP. if(nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R) { assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_N_LP && this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_N_LP); } // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(!rpcPic->getReconMark()) { continue; } if (rpcPic->getPOC() == this->getPOC()) { continue; } // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture // in decoding order shall precede the IRAP picture in output order. // (Note that any picture following in output order would be present in the DPB) if(rpcPic->getSlice(0)->getPicOutputFlag() == 1 && !this->getNoOutputPriorPicsFlag()) { if(nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) { assert(rpcPic->getPOC() < this->getPOC()); } } // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture // in decoding order shall precede any RADL picture associated with the IRAP // picture in output order. if(rpcPic->getSlice(0)->getPicOutputFlag() == 1) { if((nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R)) { // rpcPic precedes the IRAP in decoding order if(this->getAssociatedIRAPPOC() > rpcPic->getSlice(0)->getAssociatedIRAPPOC()) { // rpcPic must not be the IRAP picture if(this->getAssociatedIRAPPOC() != rpcPic->getPOC()) { assert(rpcPic->getPOC() < this->getPOC()); } } } } // When a picture is a leading picture, it shall precede, in decoding order, // all trailing pictures that are associated with the same IRAP picture. if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R) { if(rpcPic->getSlice(0)->getAssociatedIRAPPOC() == this->getAssociatedIRAPPOC()) { // rpcPic is a picture that preceded the leading in decoding order since it exist in the DPB // rpcPic would violate the constraint if it was a trailing picture assert(rpcPic->getPOC() <= this->getAssociatedIRAPPOC()); } } // Any RASL picture associated with a CRA or BLA picture shall precede any // RADL picture associated with the CRA or BLA picture in output order if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) { if((this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA) && this->getAssociatedIRAPPOC() == rpcPic->getSlice(0)->getAssociatedIRAPPOC()) { if(rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R) { assert(rpcPic->getPOC() > this->getPOC()); } } } // Any RASL picture associated with a CRA picture shall follow, in output // order, any IRAP picture that precedes the CRA picture in decoding order. if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) { if(this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA) { if(rpcPic->getSlice(0)->getPOC() < this->getAssociatedIRAPPOC() && (rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) { assert(this->getPOC() > rpcPic->getSlice(0)->getPOC()); } } } } } /** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet. */ Void TComSlice::applyReferencePictureSet( TComList& rcListPic, const TComReferencePictureSet *pReferencePictureSet) { TComPic* rpcPic; Int i, isReference; checkLeadingPictureRestrictions(rcListPic); // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(!rpcPic->getSlice( 0 )->isReferenced()) { continue; } isReference = 0; // loop through all pictures in the Reference Picture Set // to see if the picture should be kept as reference picture for(i=0;igetNumberOfPositivePictures()+pReferencePictureSet->getNumberOfNegativePictures();i++) { if(!rpcPic->getIsLongTerm() && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i)) { isReference = 1; rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); rpcPic->setIsLongTerm(0); } } for(;igetNumberOfPictures();i++) { if(pReferencePictureSet->getCheckLTMSBPresent(i)==true) { if(rpcPic->getIsLongTerm() && (rpcPic->getPicSym()->getSlice(0)->getPOC()) == pReferencePictureSet->getPOC(i)) { isReference = 1; rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); } } else { Int pocCycle = 1<getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC() & (pocCycle-1); Int refPoc = pReferencePictureSet->getPOC(i) & (pocCycle-1); if(rpcPic->getIsLongTerm() && curPoc == refPoc) { isReference = 1; rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); } } } // mark the picture as "unused for reference" if it is not in // the Reference Picture Set if(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && isReference == 0) { rpcPic->getSlice( 0 )->setReferenced( false ); rpcPic->setUsedByCurr(0); rpcPic->setIsLongTerm(0); } //check that pictures of higher temporal layers are not used assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getTLayer()<=this->getTLayer()); //check that pictures of higher or equal temporal layer are not in the RPS if the current picture is a TSA picture if(this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_R || this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N) { assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getTLayer()getTLayer()); } //check that pictures marked as temporal layer non-reference pictures are not used for reference if(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && rpcPic->getTLayer()==this->getTLayer()) { assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getSlice( 0 )->getTemporalLayerNonReferenceFlag()==false); } } } /** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet. */ Int TComSlice::checkThatAllRefPicsAreAvailable( TComList& rcListPic, const TComReferencePictureSet *pReferencePictureSet, Bool printErrors, Int pocRandomAccess, Bool bUseRecoveryPoint) { Int atLeastOneUnabledByRecoveryPoint = 0; Int atLeastOneFlushedByPreviousIDR = 0; TComPic* rpcPic; Int i, isAvailable; Int atLeastOneLost = 0; Int atLeastOneRemoved = 0; Int iPocLost = 0; // loop through all long-term pictures in the Reference Picture Set // to see if the picture should be kept as reference picture for(i=pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures();igetNumberOfPictures();i++) { isAvailable = 0; // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(pReferencePictureSet->getCheckLTMSBPresent(i)==true) { if(rpcPic->getIsLongTerm() && (rpcPic->getPicSym()->getSlice(0)->getPOC()) == pReferencePictureSet->getPOC(i) && rpcPic->getSlice(0)->isReferenced()) { if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) { isAvailable = 0; } else { isAvailable = 1; } } } else { Int pocCycle = 1<getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC() & (pocCycle-1); Int refPoc = pReferencePictureSet->getPOC(i) & (pocCycle-1); if(rpcPic->getIsLongTerm() && curPoc == refPoc && rpcPic->getSlice(0)->isReferenced()) { if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) { isAvailable = 0; } else { isAvailable = 1; } } } } // if there was no such long-term check the short terms if(!isAvailable) { iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); Int pocCycle = 1 << rpcPic->getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC(); Int refPoc = pReferencePictureSet->getPOC(i); if (!pReferencePictureSet->getCheckLTMSBPresent(i)) { curPoc = curPoc & (pocCycle - 1); refPoc = refPoc & (pocCycle - 1); } if (rpcPic->getSlice(0)->isReferenced() && curPoc == refPoc) { if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) { isAvailable = 0; } else { isAvailable = 1; rpcPic->setIsLongTerm(1); break; } } } } // report that a picture is lost if it is in the Reference Picture Set // but not available as reference picture if(isAvailable == 0) { if (this->getPOC() + pReferencePictureSet->getDeltaPOC(i) >= pocRandomAccess) { if(!pReferencePictureSet->getUsed(i) ) { if(printErrors) { printf("\nLong-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); } atLeastOneRemoved = 1; } else { if(printErrors) { printf("\nLong-term reference picture with POC = %3d is lost or not correctly decoded!", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); } atLeastOneLost = 1; iPocLost=this->getPOC() + pReferencePictureSet->getDeltaPOC(i); } } else if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess) { atLeastOneUnabledByRecoveryPoint = 1; } else if(bUseRecoveryPoint && (this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_N_LP || this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_W_RADL)) { atLeastOneFlushedByPreviousIDR = 1; } } } // loop through all short-term pictures in the Reference Picture Set // to see if the picture should be kept as reference picture for(i=0;igetNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures();i++) { isAvailable = 0; // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(!rpcPic->getIsLongTerm() && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i) && rpcPic->getSlice(0)->isReferenced()) { if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) { isAvailable = 0; } else { isAvailable = 1; } } } // report that a picture is lost if it is in the Reference Picture Set // but not available as reference picture if(isAvailable == 0) { if (this->getPOC() + pReferencePictureSet->getDeltaPOC(i) >= pocRandomAccess) { if(!pReferencePictureSet->getUsed(i) ) { if(printErrors) { printf("\nShort-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); } atLeastOneRemoved = 1; } else { if(printErrors) { printf("\nShort-term reference picture with POC = %3d is lost or not correctly decoded!", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); } atLeastOneLost = 1; iPocLost=this->getPOC() + pReferencePictureSet->getDeltaPOC(i); } } else if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess) { atLeastOneUnabledByRecoveryPoint = 1; } else if(bUseRecoveryPoint && (this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_N_LP || this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_W_RADL)) { atLeastOneFlushedByPreviousIDR = 1; } } } if(atLeastOneUnabledByRecoveryPoint || atLeastOneFlushedByPreviousIDR) { return -1; } if(atLeastOneLost) { return iPocLost+1; } if(atLeastOneRemoved) { return -2; } else { return 0; } } /** Function for constructing an explicit Reference Picture Set out of the available pictures in a referenced Reference Picture Set */ Void TComSlice::createExplicitReferencePictureSetFromReference( TComList& rcListPic, const TComReferencePictureSet *pReferencePictureSet, Bool isRAP, Int pocRandomAccess, Bool bUseRecoveryPoint, const Bool bEfficientFieldIRAPEnabled) { TComPic* rpcPic; Int i, j; Int k = 0; Int nrOfNegativePictures = 0; Int nrOfPositivePictures = 0; TComReferencePictureSet* pLocalRPS = this->getLocalRPS(); (*pLocalRPS)=TComReferencePictureSet(); Bool irapIsInRPS = false; // Used when bEfficientFieldIRAPEnabled==true // loop through all pictures in the Reference Picture Set for(i=0;igetNumberOfPictures();i++) { j = 0; // loop through all pictures in the reference picture buffer TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { j++; rpcPic = *(iterPic++); if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i) && rpcPic->getSlice(0)->isReferenced()) { // This picture exists as a reference picture // and should be added to the explicit Reference Picture Set pLocalRPS->setDeltaPOC(k, pReferencePictureSet->getDeltaPOC(i)); pLocalRPS->setUsed(k, pReferencePictureSet->getUsed(i) && (!isRAP)); if (bEfficientFieldIRAPEnabled) { pLocalRPS->setUsed(k, pLocalRPS->getUsed(k) && !(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) ); } if(pLocalRPS->getDeltaPOC(k) < 0) { nrOfNegativePictures++; } else { if(bEfficientFieldIRAPEnabled && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getAssociatedIRAPPOC() && this->getAssociatedIRAPPOC() == this->getPOC()+1) { irapIsInRPS = true; } nrOfPositivePictures++; } k++; } } } Bool useNewRPS = false; // if current picture is complimentary field associated to IRAP, add the IRAP to its RPS. if(bEfficientFieldIRAPEnabled && m_pcPic->isField() && !irapIsInRPS) { TComList::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end()) { rpcPic = *(iterPic++); if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getAssociatedIRAPPOC() && this->getAssociatedIRAPPOC() == this->getPOC()+1) { pLocalRPS->setDeltaPOC(k, 1); pLocalRPS->setUsed(k, true); nrOfPositivePictures++; k ++; useNewRPS = true; } } } pLocalRPS->setNumberOfNegativePictures(nrOfNegativePictures); pLocalRPS->setNumberOfPositivePictures(nrOfPositivePictures); pLocalRPS->setNumberOfPictures(nrOfNegativePictures+nrOfPositivePictures); // This is a simplistic inter rps example. A smarter encoder will look for a better reference RPS to do the // inter RPS prediction with. Here we just use the reference used by pReferencePictureSet. // If pReferencePictureSet is not inter_RPS_predicted, then inter_RPS_prediction is for the current RPS also disabled. if (!pReferencePictureSet->getInterRPSPrediction() || useNewRPS ) { pLocalRPS->setInterRPSPrediction(false); pLocalRPS->setNumRefIdc(0); } else { Int rIdx = this->getRPSidx() - pReferencePictureSet->getDeltaRIdxMinus1() - 1; Int deltaRPS = pReferencePictureSet->getDeltaRPS(); const TComReferencePictureSet* pcRefRPS = this->getSPS()->getRPSList()->getReferencePictureSet(rIdx); Int iRefPics = pcRefRPS->getNumberOfPictures(); Int iNewIdc=0; for(i=0; i<= iRefPics; i++) { Int deltaPOC = ((i != iRefPics)? pcRefRPS->getDeltaPOC(i) : 0); // check if the reference abs POC is >= 0 Int iRefIdc = 0; for (j=0; j < pLocalRPS->getNumberOfPictures(); j++) // loop through the pictures in the new RPS { if ( (deltaPOC + deltaRPS) == pLocalRPS->getDeltaPOC(j)) { if (pLocalRPS->getUsed(j)) { iRefIdc = 1; } else { iRefIdc = 2; } } } pLocalRPS->setRefIdc(i, iRefIdc); iNewIdc++; } pLocalRPS->setInterRPSPrediction(true); pLocalRPS->setNumRefIdc(iNewIdc); pLocalRPS->setDeltaRPS(deltaRPS); pLocalRPS->setDeltaRIdxMinus1(pReferencePictureSet->getDeltaRIdxMinus1() + this->getSPS()->getRPSList()->getNumberOfReferencePictureSets() - this->getRPSidx()); } this->setRPS(pLocalRPS); this->setRPSidx(-1); } //! get AC and DC values for weighted pred Void TComSlice::getWpAcDcParam(WPACDCParam *&wp) { wp = m_weightACDCParam; } //! init AC and DC values for weighted pred Void TComSlice::initWpAcDcParam() { for(Int iComp = 0; iComp < MAX_NUM_COMPONENT; iComp++ ) { m_weightACDCParam[iComp].iAC = 0; m_weightACDCParam[iComp].iDC = 0; } } //! get tables for weighted prediction Void TComSlice::getWpScaling( RefPicList e, Int iRefIdx, WPScalingParam *&wp ) { assert (ebPresentFlag = false; pwp->uiLog2WeightDenom = 0; pwp->uiLog2WeightDenom = 0; pwp->iWeight = 1; pwp->iOffset = 0; } } } } //! init WP table Void TComSlice::initWpScaling(const TComSPS *sps) { const Bool bUseHighPrecisionPredictionWeighting = sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); for ( Int e=0 ; ebPresentFlag ) { // Inferring values not present : pwp->iWeight = (1 << pwp->uiLog2WeightDenom); pwp->iOffset = 0; } const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (sps->getBitDepth(toChannelType(ComponentID(yuv)))-8)); pwp->w = pwp->iWeight; pwp->o = pwp->iOffset * offsetScalingFactor; //NOTE: This value of the ".o" variable is never used - .o is set immediately before it gets used pwp->shift = pwp->uiLog2WeightDenom; pwp->round = (pwp->uiLog2WeightDenom>=1) ? (1 << (pwp->uiLog2WeightDenom-1)) : (0); } } } } // ------------------------------------------------------------------------------------------------ // Video parameter set (VPS) // ------------------------------------------------------------------------------------------------ TComVPS::TComVPS() : m_VPSId ( 0) , m_uiMaxTLayers ( 1) , m_uiMaxLayers ( 1) , m_bTemporalIdNestingFlag (false) , m_numHrdParameters ( 0) , m_maxNuhReservedZeroLayerId ( 0) , m_hrdParameters () , m_hrdOpSetIdx () , m_cprmsPresentFlag () { for( Int i = 0; i < MAX_TLAYER; i++) { m_numReorderPics[i] = 0; m_uiMaxDecPicBuffering[i] = 1; m_uiMaxLatencyIncrease[i] = 0; } } TComVPS::~TComVPS() { } // ------------------------------------------------------------------------------------------------ // Sequence parameter set (SPS) // ------------------------------------------------------------------------------------------------ TComSPSRExt::TComSPSRExt() : m_transformSkipRotationEnabledFlag (false) , m_transformSkipContextEnabledFlag (false) // m_rdpcmEnabledFlag initialized below , m_extendedPrecisionProcessingFlag (false) , m_intraSmoothingDisabledFlag (false) , m_highPrecisionOffsetsEnabledFlag (false) , m_persistentRiceAdaptationEnabledFlag(false) , m_cabacBypassAlignmentEnabledFlag (false) { for (UInt signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++) { m_rdpcmEnabledFlag[signallingModeIndex] = false; } } TComSPS::TComSPS() : m_SPSId ( 0) , m_VPSId ( 0) , m_chromaFormatIdc (CHROMA_420) , m_uiMaxTLayers ( 1) // Structure , m_picWidthInLumaSamples (352) , m_picHeightInLumaSamples (288) , m_log2MinCodingBlockSize ( 0) , m_log2DiffMaxMinCodingBlockSize(0) , m_uiMaxCUWidth ( 32) , m_uiMaxCUHeight ( 32) , m_uiMaxTotalCUDepth ( 3) , m_bLongTermRefsPresent (false) , m_uiQuadtreeTULog2MaxSize ( 0) , m_uiQuadtreeTULog2MinSize ( 0) , m_uiQuadtreeTUMaxDepthInter ( 0) , m_uiQuadtreeTUMaxDepthIntra ( 0) // Tool list , m_usePCM (false) , m_pcmLog2MaxSize ( 5) , m_uiPCMLog2MinSize ( 7) , m_bPCMFilterDisableFlag (false) , m_uiBitsForPOC ( 8) , m_numLongTermRefPicSPS ( 0) , m_uiMaxTrSize ( 32) , m_bUseSAO (false) , m_bTemporalIdNestingFlag (false) , m_scalingListEnabledFlag (false) , m_useStrongIntraSmoothing (false) , m_vuiParametersPresentFlag (false) , m_vuiParameters () { for(Int ch=0; ch= 0; k--) { Int temp = getDeltaPOC(k); if (deltaPOC < temp) { setDeltaPOC(k+1, temp); setUsed(k+1, getUsed(k)); setDeltaPOC(k, deltaPOC); setUsed(k, used); } } } // flip the negative values to largest first Int numNegPics = getNumberOfNegativePictures(); for(Int j=0, k=numNegPics-1; j < numNegPics>>1; j++, k--) { Int deltaPOC = getDeltaPOC(j); Bool used = getUsed(j); setDeltaPOC(j, getDeltaPOC(k)); setUsed(j, getUsed(k)); setDeltaPOC(k, deltaPOC); setUsed(k, used); } } /** Prints the deltaPOC and RefIdc (if available) values in the RPS. * A "*" is added to the deltaPOC value if it is Used bu current. * \returns Void */ Void TComReferencePictureSet::printDeltaPOC() const { printf("DeltaPOC = { "); for(Int j=0; j < getNumberOfPictures(); j++) { printf("%d%s ", getDeltaPOC(j), (getUsed(j)==1)?"*":""); } if (getInterRPSPrediction()) { printf("}, RefIdc = { "); for(Int j=0; j < getNumRefIdc(); j++) { printf("%d ", getRefIdc(j)); } } printf("}\n"); } TComRefPicListModification::TComRefPicListModification() : m_refPicListModificationFlagL0 (false) , m_refPicListModificationFlagL1 (false) { ::memset( m_RefPicSetIdxL0, 0, sizeof(m_RefPicSetIdxL0) ); ::memset( m_RefPicSetIdxL1, 0, sizeof(m_RefPicSetIdxL1) ); } TComRefPicListModification::~TComRefPicListModification() { } TComScalingList::TComScalingList() { for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) { m_scalingListCoef[sizeId][listId].resize(min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])); } } } /** set default quantization matrix to array */ Void TComScalingList::setDefaultScalingList() { for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(UInt listId=0;listId= 0; predListIdx-=predListStep) { if( !memcmp(getScalingListAddress(sizeId,listId),((listId == predListIdx) ? getScalingListDefaultAddress(sizeId, predListIdx): getScalingListAddress(sizeId, predListIdx)),sizeof(Int)*min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])) // check value of matrix && ((sizeId < SCALING_LIST_16x16) || (getScalingListDC(sizeId,listId) == getScalingListDC(sizeId,predListIdx)))) // check DC value { setRefMatrixId(sizeId, listId, predListIdx); setScalingListPredModeFlag(sizeId, listId, false); return; } } setScalingListPredModeFlag(sizeId, listId, true); } static Void outputScalingListHelp(std::ostream &os) { os << "The scaling list file specifies all matrices and their DC values; none can be missing,\n" "but their order is arbitrary.\n\n" "The matrices are specified by:\n" "\n" " ,,,....\n\n" " Line-feeds can be added arbitrarily between values, and the number of values needs to be\n" " at least the number of entries for the matrix (superfluous entries are ignored).\n" " The is text on the same line as the matrix that is not checked\n" " except to ensure that the matrix name token is unique. It is recommended that it is ' ='\n" " The values in the matrices are the absolute values (0-255), not the delta values as\n" " exchanged between the encoder and decoder\n\n" "The DC values (for matrix sizes larger than 8x8) are specified by:\n" "_DC\n" " \n"; os << "The permitted matrix names are:\n"; for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) { for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) { if ((sizeIdc!=SCALING_LIST_32x32) || (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) == 0)) { os << " " << MatrixType[sizeIdc][listIdc] << '\n'; } } } } Void TComScalingList::outputScalingLists(std::ostream &os) const { for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) { const UInt size = min(8,4<<(sizeIdc)); for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) { if ((sizeIdc!=SCALING_LIST_32x32) || (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) == 0)) { const Int *src = getScalingListAddress(sizeIdc, listIdc); os << (MatrixType[sizeIdc][listIdc]) << " =\n "; for(UInt y=0; y SCALING_LIST_8x8) { os << MatrixType_DC[sizeIdc][listIdc] << " = \n " << std::setw(3) << getScalingListDC(sizeIdc, listIdc) << "\n"; } os << "\n"; } } } } Bool TComScalingList::xParseScalingList(const std::string &fileName) { static const Int LINE_SIZE=1024; FILE *fp = NULL; TChar line[LINE_SIZE]; if (fileName.empty()) { fprintf(stderr, "Error: no scaling list file specified. Help on scaling lists being output\n"); outputScalingListHelp(std::cout); std::cout << "\n\nExample scaling list file using default values:\n\n"; outputScalingLists(std::cout); exit (1); return true; } else if ((fp = fopen(fileName.c_str(),"r")) == (FILE*)NULL) { fprintf(stderr, "Error: cannot open scaling list file %s for reading\n", fileName.c_str()); return true; } for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) { const UInt size = min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeIdc]); for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) { Int * const src = getScalingListAddress(sizeIdc, listIdc); if ((sizeIdc==SCALING_LIST_32x32) && (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) != 0)) // derive chroma32x32 from chroma16x16 { const Int *srcNextSmallerSize = getScalingListAddress(sizeIdc-1, listIdc); for(UInt i=0; i SCALING_LIST_8x8) ? getScalingListDC(sizeIdc-1, listIdc) : src[0]); } else { { fseek(fp, 0, SEEK_SET); Bool bFound=false; while ((!feof(fp)) && (!bFound)) { TChar *ret = fgets(line, LINE_SIZE, fp); TChar *findNamePosition= ret==NULL ? NULL : strstr(line, MatrixType[sizeIdc][listIdc]); // This could be a match against the DC string as well, so verify it isn't if (findNamePosition!= NULL && (MatrixType_DC[sizeIdc][listIdc]==NULL || strstr(line, MatrixType_DC[sizeIdc][listIdc])==NULL)) { bFound=true; } } if (!bFound) { fprintf(stderr, "Error: cannot find Matrix %s from scaling list file %s\n", MatrixType[sizeIdc][listIdc], fileName.c_str()); return true; } } for (UInt i=0; i255) { fprintf(stderr, "Error: QMatrix entry #%d of value %d for Matrix %s from scaling list file %s at file position %ld is out of range (0 to 255)\n", i, data, MatrixType[sizeIdc][listIdc], fileName.c_str(), ftell(fp)); return true; } src[i] = data; } //set DC value for default matrix check setScalingListDC(sizeIdc,listIdc,src[0]); if(sizeIdc > SCALING_LIST_8x8) { { fseek(fp, 0, SEEK_SET); Bool bFound=false; while ((!feof(fp)) && (!bFound)) { TChar *ret = fgets(line, LINE_SIZE, fp); TChar *findNamePosition= ret==NULL ? NULL : strstr(line, MatrixType_DC[sizeIdc][listIdc]); if (findNamePosition!= NULL) { // This won't be a match against the non-DC string. bFound=true; } } if (!bFound) { fprintf(stderr, "Error: cannot find DC Matrix %s from scaling list file %s\n", MatrixType_DC[sizeIdc][listIdc], fileName.c_str()); return true; } } Int data; if (fscanf(fp, "%d,", &data)!=1) { fprintf(stderr, "Error: cannot read DC %s from scaling list file %s at file position %ld\n", MatrixType_DC[sizeIdc][listIdc], fileName.c_str(), ftell(fp)); return true; } if (data<0 || data>255) { fprintf(stderr, "Error: DC value %d for Matrix %s from scaling list file %s at file position %ld is out of range (0 to 255)\n", data, MatrixType[sizeIdc][listIdc], fileName.c_str(), ftell(fp)); return true; } //overwrite DC value when size of matrix is larger than 16x16 setScalingListDC(sizeIdc,listIdc,data); } } } } // std::cout << "\n\nRead scaling lists of:\n\n"; // outputScalingLists(std::cout); fclose(fp); return false; } /** get default address of quantization matrix * \param sizeId size index * \param listId list index * \returns pointer of quantization matrix */ const Int* TComScalingList::getScalingListDefaultAddress(UInt sizeId, UInt listId) { const Int *src = 0; switch(sizeId) { case SCALING_LIST_4x4: src = g_quantTSDefault4x4; break; case SCALING_LIST_8x8: case SCALING_LIST_16x16: case SCALING_LIST_32x32: src = (listId < (SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) ) ? g_quantIntraDefault8x8 : g_quantInterDefault8x8; break; default: assert(0); src = NULL; break; } return src; } /** process of default matrix * \param sizeId size index * \param listId index of input matrix */ Void TComScalingList::processDefaultMatrix(UInt sizeId, UInt listId) { ::memcpy(getScalingListAddress(sizeId, listId),getScalingListDefaultAddress(sizeId,listId),sizeof(Int)*min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])); setScalingListDC(sizeId,listId,SCALING_LIST_DC); } /** check DC value of matrix for default matrix signaling */ Void TComScalingList::checkDcOfMatrix() { for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) { //check default matrix? if(getScalingListDC(sizeId,listId) == 0) { processDefaultMatrix(sizeId, listId); } } } } ParameterSetManager::ParameterSetManager() : m_vpsMap(MAX_NUM_VPS) , m_spsMap(MAX_NUM_SPS) , m_ppsMap(MAX_NUM_PPS) , m_activeVPSId(-1) , m_activeSPSId(-1) { } ParameterSetManager::~ParameterSetManager() { } //! activate a SPS from a active parameter sets SEI message //! \returns true, if activation is successful //Bool ParameterSetManager::activateSPSWithSEI(Int spsId) //{ // TComSPS *sps = m_spsMap.getPS(spsId); // if (sps) // { // Int vpsId = sps->getVPSId(); // TComVPS *vps = m_vpsMap.getPS(vpsId); // if (vps) // { // m_activeVPS = *(vps); // m_activeSPS = *(sps); // return true; // } // else // { // printf("Warning: tried to activate SPS using an Active parameter sets SEI message. Referenced VPS does not exist."); // } // } // else // { // printf("Warning: tried to activate non-existing SPS using an Active parameter sets SEI message."); // } // return false; //} //! activate a PPS and depending on isIDR parameter also SPS and VPS //! \returns true, if activation is successful Bool ParameterSetManager::activatePPS(Int ppsId, Bool isIRAP) { TComPPS *pps = m_ppsMap.getPS(ppsId); if (pps) { Int spsId = pps->getSPSId(); if (!isIRAP && (spsId != m_activeSPSId )) { printf("Warning: tried to activate PPS referring to a inactive SPS at non-IDR."); } else { TComSPS *sps = m_spsMap.getPS(spsId); if (sps) { Int vpsId = sps->getVPSId(); if (!isIRAP && (vpsId != m_activeVPSId )) { printf("Warning: tried to activate PPS referring to a inactive VPS at non-IDR."); } else { TComVPS *vps =m_vpsMap.getPS(vpsId); if (vps) { m_activeVPSId = vpsId; m_activeSPSId = spsId; return true; } else { printf("Warning: tried to activate PPS that refers to a non-existing VPS."); } } } else { printf("Warning: tried to activate a PPS that refers to a non-existing SPS."); } } } else { printf("Warning: tried to activate non-existing PPS."); } // Failed to activate if reach here. m_activeSPSId=-1; m_activeVPSId=-1; return false; } template <> Void ParameterSetMap::setID(TComPPS* parameterSet, const Int psId) { parameterSet->setPPSId(psId); } template <> Void ParameterSetMap::setID(TComSPS* parameterSet, const Int psId) { parameterSet->setSPSId(psId); } ProfileTierLevel::ProfileTierLevel() : m_profileSpace (0) , m_tierFlag (Level::MAIN) , m_profileIdc (Profile::NONE) , m_levelIdc (Level::NONE) , m_progressiveSourceFlag (false) , m_interlacedSourceFlag (false) , m_nonPackedConstraintFlag(false) , m_frameOnlyConstraintFlag(false) { ::memset(m_profileCompatibilityFlag, 0, sizeof(m_profileCompatibilityFlag)); } TComPTL::TComPTL() { ::memset(m_subLayerProfilePresentFlag, 0, sizeof(m_subLayerProfilePresentFlag)); ::memset(m_subLayerLevelPresentFlag, 0, sizeof(m_subLayerLevelPresentFlag )); } Void calculateParameterSetChangedFlag(Bool &bChanged, const std::vector *pOldData, const std::vector *pNewData) { if (!bChanged) { if ((pOldData==0 && pNewData!=0) || (pOldData!=0 && pNewData==0)) { bChanged=true; } else if (pOldData!=0 && pNewData!=0) { // compare the two if (pOldData->size() != pNewData->size()) { bChanged=true; } else { const UChar *pNewDataArray=&(*pNewData)[0]; const UChar *pOldDataArray=&(*pOldData)[0]; if (memcmp(pOldDataArray, pNewDataArray, pOldData->size())) { bChanged=true; } } } } } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComSlice.h000066400000000000000000003525411442026013100202570ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComSlice.h \brief slice header and SPS class (header) */ #ifndef __TCOMSLICE__ #define __TCOMSLICE__ #include #include #include #include "CommonDef.h" #include "TComRom.h" #include "TComList.h" #include "TComChromaFormat.h" //! \ingroup TLibCommon //! \{ class TComPic; class TComTrQuant; // ==================================================================================================================== // Constants // ==================================================================================================================== static const UInt REF_PIC_LIST_NUM_IDX=32; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Reference Picture Set class class TComReferencePictureSet { private: Int m_numberOfPictures; Int m_numberOfNegativePictures; Int m_numberOfPositivePictures; Int m_numberOfLongtermPictures; Int m_deltaPOC[MAX_NUM_REF_PICS]; Int m_POC[MAX_NUM_REF_PICS]; Bool m_used[MAX_NUM_REF_PICS]; Bool m_interRPSPrediction; Int m_deltaRIdxMinus1; Int m_deltaRPS; Int m_numRefIdc; Int m_refIdc[MAX_NUM_REF_PICS+1]; Bool m_bCheckLTMSB[MAX_NUM_REF_PICS]; Int m_pocLSBLT[MAX_NUM_REF_PICS]; Int m_deltaPOCMSBCycleLT[MAX_NUM_REF_PICS]; Bool m_deltaPocMSBPresentFlag[MAX_NUM_REF_PICS]; public: TComReferencePictureSet(); virtual ~TComReferencePictureSet(); Int getPocLSBLT(Int i) const { return m_pocLSBLT[i]; } Void setPocLSBLT(Int i, Int x) { m_pocLSBLT[i] = x; } Int getDeltaPocMSBCycleLT(Int i) const { return m_deltaPOCMSBCycleLT[i]; } Void setDeltaPocMSBCycleLT(Int i, Int x) { m_deltaPOCMSBCycleLT[i] = x; } Bool getDeltaPocMSBPresentFlag(Int i) const { return m_deltaPocMSBPresentFlag[i]; } Void setDeltaPocMSBPresentFlag(Int i, Bool x) { m_deltaPocMSBPresentFlag[i] = x; } Void setUsed(Int bufferNum, Bool used); Void setDeltaPOC(Int bufferNum, Int deltaPOC); Void setPOC(Int bufferNum, Int deltaPOC); Void setNumberOfPictures(Int numberOfPictures); Void setCheckLTMSBPresent(Int bufferNum, Bool b ); Bool getCheckLTMSBPresent(Int bufferNum) const; Int getUsed(Int bufferNum) const; Int getDeltaPOC(Int bufferNum) const; Int getPOC(Int bufferNum) const; Int getNumberOfPictures() const; Void setNumberOfNegativePictures(Int number) { m_numberOfNegativePictures = number; } Int getNumberOfNegativePictures() const { return m_numberOfNegativePictures; } Void setNumberOfPositivePictures(Int number) { m_numberOfPositivePictures = number; } Int getNumberOfPositivePictures() const { return m_numberOfPositivePictures; } Void setNumberOfLongtermPictures(Int number) { m_numberOfLongtermPictures = number; } Int getNumberOfLongtermPictures() const { return m_numberOfLongtermPictures; } Void setInterRPSPrediction(Bool flag) { m_interRPSPrediction = flag; } Bool getInterRPSPrediction() const { return m_interRPSPrediction; } Void setDeltaRIdxMinus1(Int x) { m_deltaRIdxMinus1 = x; } Int getDeltaRIdxMinus1() const { return m_deltaRIdxMinus1; } Void setDeltaRPS(Int x) { m_deltaRPS = x; } Int getDeltaRPS() const { return m_deltaRPS; } Void setNumRefIdc(Int x) { m_numRefIdc = x; } Int getNumRefIdc() const { return m_numRefIdc; } Void setRefIdc(Int bufferNum, Int refIdc); Int getRefIdc(Int bufferNum) const ; Void sortDeltaPOC(); Void printDeltaPOC() const; }; /// Reference Picture Set set class class TComRPSList { private: std::vector m_referencePictureSets; public: TComRPSList() { } virtual ~TComRPSList() { } Void create (Int numberOfEntries) { m_referencePictureSets.resize(numberOfEntries); } Void destroy () { } TComReferencePictureSet* getReferencePictureSet(Int referencePictureSetNum) { return &m_referencePictureSets[referencePictureSetNum]; } const TComReferencePictureSet* getReferencePictureSet(Int referencePictureSetNum) const { return &m_referencePictureSets[referencePictureSetNum]; } Int getNumberOfReferencePictureSets() const { return Int(m_referencePictureSets.size()); } }; /// SCALING_LIST class class TComScalingList { public: TComScalingList(); virtual ~TComScalingList() { } Int* getScalingListAddress(UInt sizeId, UInt listId) { return &(m_scalingListCoef[sizeId][listId][0]); } //!< get matrix coefficient const Int* getScalingListAddress(UInt sizeId, UInt listId) const { return &(m_scalingListCoef[sizeId][listId][0]); } //!< get matrix coefficient Void checkPredMode(UInt sizeId, UInt listId); Void setRefMatrixId(UInt sizeId, UInt listId, UInt u) { m_refMatrixId[sizeId][listId] = u; } //!< set reference matrix ID UInt getRefMatrixId(UInt sizeId, UInt listId) const { return m_refMatrixId[sizeId][listId]; } //!< get reference matrix ID const Int* getScalingListDefaultAddress(UInt sizeId, UInt listId); //!< get default matrix coefficient Void processDefaultMatrix(UInt sizeId, UInt listId); Void setScalingListDC(UInt sizeId, UInt listId, UInt u) { m_scalingListDC[sizeId][listId] = u; } //!< set DC value Int getScalingListDC(UInt sizeId, UInt listId) const { return m_scalingListDC[sizeId][listId]; } //!< get DC value Void setScalingListPredModeFlag(UInt sizeId, UInt listId, Bool bIsDPCM) { m_scalingListPredModeFlagIsDPCM[sizeId][listId] = bIsDPCM; } Bool getScalingListPredModeFlag(UInt sizeId, UInt listId) const { return m_scalingListPredModeFlagIsDPCM[sizeId][listId]; } Void checkDcOfMatrix(); Void processRefMatrix(UInt sizeId, UInt listId , UInt refListId ); Bool xParseScalingList(const std::string &fileName); Void setDefaultScalingList(); Bool checkDefaultScalingList(); private: Void outputScalingLists(std::ostream &os) const; Bool m_scalingListPredModeFlagIsDPCM [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; //!< reference list index Int m_scalingListDC [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; //!< the DC value of the matrix coefficient for 16x16 UInt m_refMatrixId [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; //!< RefMatrixID std::vector m_scalingListCoef [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; //!< quantization matrix }; class ProfileTierLevel { Int m_profileSpace; Level::Tier m_tierFlag; Profile::Name m_profileIdc; Bool m_profileCompatibilityFlag[32]; Level::Name m_levelIdc; Bool m_progressiveSourceFlag; Bool m_interlacedSourceFlag; Bool m_nonPackedConstraintFlag; Bool m_frameOnlyConstraintFlag; UInt m_bitDepthConstraintValue; ChromaFormat m_chromaFormatConstraintValue; Bool m_intraConstraintFlag; Bool m_onePictureOnlyConstraintFlag; Bool m_lowerBitRateConstraintFlag; public: ProfileTierLevel(); Int getProfileSpace() const { return m_profileSpace; } Void setProfileSpace(Int x) { m_profileSpace = x; } Level::Tier getTierFlag() const { return m_tierFlag; } Void setTierFlag(Level::Tier x) { m_tierFlag = x; } Profile::Name getProfileIdc() const { return m_profileIdc; } Void setProfileIdc(Profile::Name x) { m_profileIdc = x; } Bool getProfileCompatibilityFlag(Int i) const { return m_profileCompatibilityFlag[i]; } Void setProfileCompatibilityFlag(Int i, Bool x) { m_profileCompatibilityFlag[i] = x; } Level::Name getLevelIdc() const { return m_levelIdc; } Void setLevelIdc(Level::Name x) { m_levelIdc = x; } Bool getProgressiveSourceFlag() const { return m_progressiveSourceFlag; } Void setProgressiveSourceFlag(Bool b) { m_progressiveSourceFlag = b; } Bool getInterlacedSourceFlag() const { return m_interlacedSourceFlag; } Void setInterlacedSourceFlag(Bool b) { m_interlacedSourceFlag = b; } Bool getNonPackedConstraintFlag() const { return m_nonPackedConstraintFlag; } Void setNonPackedConstraintFlag(Bool b) { m_nonPackedConstraintFlag = b; } Bool getFrameOnlyConstraintFlag() const { return m_frameOnlyConstraintFlag; } Void setFrameOnlyConstraintFlag(Bool b) { m_frameOnlyConstraintFlag = b; } UInt getBitDepthConstraint() const { return m_bitDepthConstraintValue; } Void setBitDepthConstraint(UInt bitDepth) { m_bitDepthConstraintValue=bitDepth; } ChromaFormat getChromaFormatConstraint() const { return m_chromaFormatConstraintValue; } Void setChromaFormatConstraint(ChromaFormat fmt) { m_chromaFormatConstraintValue=fmt; } Bool getIntraConstraintFlag() const { return m_intraConstraintFlag; } Void setIntraConstraintFlag(Bool b) { m_intraConstraintFlag = b; } Bool getOnePictureOnlyConstraintFlag() const { return m_onePictureOnlyConstraintFlag;} Void setOnePictureOnlyConstraintFlag(Bool b) { m_onePictureOnlyConstraintFlag = b; } Bool getLowerBitRateConstraintFlag() const { return m_lowerBitRateConstraintFlag; } Void setLowerBitRateConstraintFlag(Bool b) { m_lowerBitRateConstraintFlag = b; } }; class TComPTL { ProfileTierLevel m_generalPTL; ProfileTierLevel m_subLayerPTL [MAX_TLAYER-1]; // max. value of max_sub_layers_minus1 is MAX_TLAYER-1 (= 6) Bool m_subLayerProfilePresentFlag [MAX_TLAYER-1]; Bool m_subLayerLevelPresentFlag [MAX_TLAYER-1]; public: TComPTL(); Bool getSubLayerProfilePresentFlag(Int i) const { return m_subLayerProfilePresentFlag[i]; } Void setSubLayerProfilePresentFlag(Int i, Bool x) { m_subLayerProfilePresentFlag[i] = x; } Bool getSubLayerLevelPresentFlag(Int i) const { return m_subLayerLevelPresentFlag[i]; } Void setSubLayerLevelPresentFlag(Int i, Bool x) { m_subLayerLevelPresentFlag[i] = x; } ProfileTierLevel* getGeneralPTL() { return &m_generalPTL; } const ProfileTierLevel* getGeneralPTL() const { return &m_generalPTL; } ProfileTierLevel* getSubLayerPTL(Int i) { return &m_subLayerPTL[i]; } const ProfileTierLevel* getSubLayerPTL(Int i) const { return &m_subLayerPTL[i]; } }; /// VPS class struct HrdSubLayerInfo { Bool fixedPicRateFlag; Bool fixedPicRateWithinCvsFlag; UInt picDurationInTcMinus1; Bool lowDelayHrdFlag; UInt cpbCntMinus1; UInt bitRateValueMinus1[MAX_CPB_CNT][2]; UInt cpbSizeValue [MAX_CPB_CNT][2]; UInt ducpbSizeValue [MAX_CPB_CNT][2]; Bool cbrFlag [MAX_CPB_CNT][2]; UInt duBitRateValue [MAX_CPB_CNT][2]; }; class TComHRD { private: Bool m_nalHrdParametersPresentFlag; Bool m_vclHrdParametersPresentFlag; Bool m_subPicCpbParamsPresentFlag; UInt m_tickDivisorMinus2; UInt m_duCpbRemovalDelayLengthMinus1; Bool m_subPicCpbParamsInPicTimingSEIFlag; UInt m_dpbOutputDelayDuLengthMinus1; UInt m_bitRateScale; UInt m_cpbSizeScale; UInt m_ducpbSizeScale; UInt m_initialCpbRemovalDelayLengthMinus1; UInt m_cpbRemovalDelayLengthMinus1; UInt m_dpbOutputDelayLengthMinus1; HrdSubLayerInfo m_HRD[MAX_TLAYER]; public: TComHRD() :m_nalHrdParametersPresentFlag (0) ,m_vclHrdParametersPresentFlag (0) ,m_subPicCpbParamsPresentFlag (false) ,m_tickDivisorMinus2 (0) ,m_duCpbRemovalDelayLengthMinus1 (0) ,m_subPicCpbParamsInPicTimingSEIFlag (false) ,m_dpbOutputDelayDuLengthMinus1 (0) ,m_bitRateScale (0) ,m_cpbSizeScale (0) ,m_initialCpbRemovalDelayLengthMinus1(23) ,m_cpbRemovalDelayLengthMinus1 (23) ,m_dpbOutputDelayLengthMinus1 (23) {} virtual ~TComHRD() {} Void setNalHrdParametersPresentFlag( Bool flag ) { m_nalHrdParametersPresentFlag = flag; } Bool getNalHrdParametersPresentFlag( ) const { return m_nalHrdParametersPresentFlag; } Void setVclHrdParametersPresentFlag( Bool flag ) { m_vclHrdParametersPresentFlag = flag; } Bool getVclHrdParametersPresentFlag( ) const { return m_vclHrdParametersPresentFlag; } Void setSubPicCpbParamsPresentFlag( Bool flag ) { m_subPicCpbParamsPresentFlag = flag; } Bool getSubPicCpbParamsPresentFlag( ) const { return m_subPicCpbParamsPresentFlag; } Void setTickDivisorMinus2( UInt value ) { m_tickDivisorMinus2 = value; } UInt getTickDivisorMinus2( ) const { return m_tickDivisorMinus2; } Void setDuCpbRemovalDelayLengthMinus1( UInt value ) { m_duCpbRemovalDelayLengthMinus1 = value; } UInt getDuCpbRemovalDelayLengthMinus1( ) const { return m_duCpbRemovalDelayLengthMinus1; } Void setSubPicCpbParamsInPicTimingSEIFlag( Bool flag) { m_subPicCpbParamsInPicTimingSEIFlag = flag; } Bool getSubPicCpbParamsInPicTimingSEIFlag( ) const { return m_subPicCpbParamsInPicTimingSEIFlag; } Void setDpbOutputDelayDuLengthMinus1(UInt value ) { m_dpbOutputDelayDuLengthMinus1 = value; } UInt getDpbOutputDelayDuLengthMinus1( ) const { return m_dpbOutputDelayDuLengthMinus1; } Void setBitRateScale( UInt value ) { m_bitRateScale = value; } UInt getBitRateScale( ) const { return m_bitRateScale; } Void setCpbSizeScale( UInt value ) { m_cpbSizeScale = value; } UInt getCpbSizeScale( ) const { return m_cpbSizeScale; } Void setDuCpbSizeScale( UInt value ) { m_ducpbSizeScale = value; } UInt getDuCpbSizeScale( ) const { return m_ducpbSizeScale; } Void setInitialCpbRemovalDelayLengthMinus1( UInt value ) { m_initialCpbRemovalDelayLengthMinus1 = value; } UInt getInitialCpbRemovalDelayLengthMinus1( ) const { return m_initialCpbRemovalDelayLengthMinus1; } Void setCpbRemovalDelayLengthMinus1( UInt value ) { m_cpbRemovalDelayLengthMinus1 = value; } UInt getCpbRemovalDelayLengthMinus1( ) const { return m_cpbRemovalDelayLengthMinus1; } Void setDpbOutputDelayLengthMinus1( UInt value ) { m_dpbOutputDelayLengthMinus1 = value; } UInt getDpbOutputDelayLengthMinus1( ) const { return m_dpbOutputDelayLengthMinus1; } Void setFixedPicRateFlag( Int layer, Bool flag ) { m_HRD[layer].fixedPicRateFlag = flag; } Bool getFixedPicRateFlag( Int layer ) const { return m_HRD[layer].fixedPicRateFlag; } Void setFixedPicRateWithinCvsFlag( Int layer, Bool flag ) { m_HRD[layer].fixedPicRateWithinCvsFlag = flag; } Bool getFixedPicRateWithinCvsFlag( Int layer ) const { return m_HRD[layer].fixedPicRateWithinCvsFlag; } Void setPicDurationInTcMinus1( Int layer, UInt value ) { m_HRD[layer].picDurationInTcMinus1 = value; } UInt getPicDurationInTcMinus1( Int layer ) const { return m_HRD[layer].picDurationInTcMinus1; } Void setLowDelayHrdFlag( Int layer, Bool flag ) { m_HRD[layer].lowDelayHrdFlag = flag; } Bool getLowDelayHrdFlag( Int layer ) const { return m_HRD[layer].lowDelayHrdFlag; } Void setCpbCntMinus1( Int layer, UInt value ) { m_HRD[layer].cpbCntMinus1 = value; } UInt getCpbCntMinus1( Int layer ) const { return m_HRD[layer].cpbCntMinus1; } Void setBitRateValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl, UInt value ) { m_HRD[layer].bitRateValueMinus1[cpbcnt][nalOrVcl] = value; } UInt getBitRateValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl ) const { return m_HRD[layer].bitRateValueMinus1[cpbcnt][nalOrVcl]; } Void setCpbSizeValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl, UInt value ) { m_HRD[layer].cpbSizeValue[cpbcnt][nalOrVcl] = value; } UInt getCpbSizeValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl ) const { return m_HRD[layer].cpbSizeValue[cpbcnt][nalOrVcl]; } Void setDuCpbSizeValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl, UInt value ) { m_HRD[layer].ducpbSizeValue[cpbcnt][nalOrVcl] = value; } UInt getDuCpbSizeValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl ) const { return m_HRD[layer].ducpbSizeValue[cpbcnt][nalOrVcl]; } Void setDuBitRateValueMinus1( Int layer, Int cpbcnt, Int nalOrVcl, UInt value ) { m_HRD[layer].duBitRateValue[cpbcnt][nalOrVcl] = value; } UInt getDuBitRateValueMinus1(Int layer, Int cpbcnt, Int nalOrVcl ) const { return m_HRD[layer].duBitRateValue[cpbcnt][nalOrVcl]; } Void setCbrFlag( Int layer, Int cpbcnt, Int nalOrVcl, Bool value ) { m_HRD[layer].cbrFlag[cpbcnt][nalOrVcl] = value; } Bool getCbrFlag( Int layer, Int cpbcnt, Int nalOrVcl ) const { return m_HRD[layer].cbrFlag[cpbcnt][nalOrVcl]; } Bool getCpbDpbDelaysPresentFlag( ) const { return getNalHrdParametersPresentFlag() || getVclHrdParametersPresentFlag(); } }; class TimingInfo { Bool m_timingInfoPresentFlag; UInt m_numUnitsInTick; UInt m_timeScale; Bool m_pocProportionalToTimingFlag; Int m_numTicksPocDiffOneMinus1; public: TimingInfo() : m_timingInfoPresentFlag (false) , m_numUnitsInTick (1001) , m_timeScale (60000) , m_pocProportionalToTimingFlag(false) , m_numTicksPocDiffOneMinus1 (0) {} Void setTimingInfoPresentFlag( Bool flag ) { m_timingInfoPresentFlag = flag; } Bool getTimingInfoPresentFlag( ) const { return m_timingInfoPresentFlag; } Void setNumUnitsInTick( UInt value ) { m_numUnitsInTick = value; } UInt getNumUnitsInTick( ) const { return m_numUnitsInTick; } Void setTimeScale( UInt value ) { m_timeScale = value; } UInt getTimeScale( ) const { return m_timeScale; } Void setPocProportionalToTimingFlag(Bool x) { m_pocProportionalToTimingFlag = x; } Bool getPocProportionalToTimingFlag( ) const { return m_pocProportionalToTimingFlag; } Void setNumTicksPocDiffOneMinus1(Int x) { m_numTicksPocDiffOneMinus1 = x; } Int getNumTicksPocDiffOneMinus1( ) const { return m_numTicksPocDiffOneMinus1; } }; struct ChromaQpAdj { union { struct { Int CbOffset; Int CrOffset; } comp; Int offset[2]; /* two chroma components */ } u; }; class TComVPS { private: Int m_VPSId; UInt m_uiMaxTLayers; UInt m_uiMaxLayers; Bool m_bTemporalIdNestingFlag; UInt m_numReorderPics[MAX_TLAYER]; UInt m_uiMaxDecPicBuffering[MAX_TLAYER]; UInt m_uiMaxLatencyIncrease[MAX_TLAYER]; // Really max latency increase plus 1 (value 0 expresses no limit) UInt m_numHrdParameters; UInt m_maxNuhReservedZeroLayerId; std::vector m_hrdParameters; std::vector m_hrdOpSetIdx; std::vector m_cprmsPresentFlag; UInt m_numOpSets; Bool m_layerIdIncludedFlag[MAX_VPS_OP_SETS_PLUS1][MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1]; TComPTL m_pcPTL; TimingInfo m_timingInfo; public: TComVPS(); virtual ~TComVPS(); Void createHrdParamBuffer() { m_hrdParameters.resize(getNumHrdParameters()); m_hrdOpSetIdx.resize(getNumHrdParameters()); m_cprmsPresentFlag.resize(getNumHrdParameters()); } TComHRD* getHrdParameters( UInt i ) { return &m_hrdParameters[ i ]; } const TComHRD* getHrdParameters( UInt i ) const { return &m_hrdParameters[ i ]; } UInt getHrdOpSetIdx( UInt i ) const { return m_hrdOpSetIdx[ i ]; } Void setHrdOpSetIdx( UInt val, UInt i ) { m_hrdOpSetIdx[ i ] = val; } Bool getCprmsPresentFlag( UInt i ) const { return m_cprmsPresentFlag[ i ]; } Void setCprmsPresentFlag( Bool val, UInt i ) { m_cprmsPresentFlag[ i ] = val; } Int getVPSId() const { return m_VPSId; } Void setVPSId(Int i) { m_VPSId = i; } UInt getMaxTLayers() const { return m_uiMaxTLayers; } Void setMaxTLayers(UInt t) { m_uiMaxTLayers = t; } UInt getMaxLayers() const { return m_uiMaxLayers; } Void setMaxLayers(UInt l) { m_uiMaxLayers = l; } Bool getTemporalNestingFlag() const { return m_bTemporalIdNestingFlag; } Void setTemporalNestingFlag(Bool t) { m_bTemporalIdNestingFlag = t; } Void setNumReorderPics(UInt v, UInt tLayer) { m_numReorderPics[tLayer] = v; } UInt getNumReorderPics(UInt tLayer) const { return m_numReorderPics[tLayer]; } Void setMaxDecPicBuffering(UInt v, UInt tLayer) { assert(tLayer < MAX_TLAYER); m_uiMaxDecPicBuffering[tLayer] = v; } UInt getMaxDecPicBuffering(UInt tLayer) const { return m_uiMaxDecPicBuffering[tLayer]; } Void setMaxLatencyIncrease(UInt v, UInt tLayer) { m_uiMaxLatencyIncrease[tLayer] = v; } UInt getMaxLatencyIncrease(UInt tLayer) const { return m_uiMaxLatencyIncrease[tLayer]; } UInt getNumHrdParameters() const { return m_numHrdParameters; } Void setNumHrdParameters(UInt v) { m_numHrdParameters = v; } UInt getMaxNuhReservedZeroLayerId() const { return m_maxNuhReservedZeroLayerId; } Void setMaxNuhReservedZeroLayerId(UInt v) { m_maxNuhReservedZeroLayerId = v; } UInt getMaxOpSets() const { return m_numOpSets; } Void setMaxOpSets(UInt v) { m_numOpSets = v; } Bool getLayerIdIncludedFlag(UInt opsIdx, UInt id) const { return m_layerIdIncludedFlag[opsIdx][id]; } Void setLayerIdIncludedFlag(Bool v, UInt opsIdx, UInt id) { m_layerIdIncludedFlag[opsIdx][id] = v; } TComPTL* getPTL() { return &m_pcPTL; } const TComPTL* getPTL() const { return &m_pcPTL; } TimingInfo* getTimingInfo() { return &m_timingInfo; } const TimingInfo* getTimingInfo() const { return &m_timingInfo; } }; class TComVUI { private: Bool m_aspectRatioInfoPresentFlag; Int m_aspectRatioIdc; Int m_sarWidth; Int m_sarHeight; Bool m_overscanInfoPresentFlag; Bool m_overscanAppropriateFlag; Bool m_videoSignalTypePresentFlag; Int m_videoFormat; Bool m_videoFullRangeFlag; Bool m_colourDescriptionPresentFlag; Int m_colourPrimaries; Int m_transferCharacteristics; Int m_matrixCoefficients; Bool m_chromaLocInfoPresentFlag; Int m_chromaSampleLocTypeTopField; Int m_chromaSampleLocTypeBottomField; Bool m_neutralChromaIndicationFlag; Bool m_fieldSeqFlag; Window m_defaultDisplayWindow; Bool m_frameFieldInfoPresentFlag; Bool m_hrdParametersPresentFlag; Bool m_bitstreamRestrictionFlag; Bool m_tilesFixedStructureFlag; Bool m_motionVectorsOverPicBoundariesFlag; Bool m_restrictedRefPicListsFlag; Int m_minSpatialSegmentationIdc; Int m_maxBytesPerPicDenom; Int m_maxBitsPerMinCuDenom; Int m_log2MaxMvLengthHorizontal; Int m_log2MaxMvLengthVertical; TComHRD m_hrdParameters; TimingInfo m_timingInfo; public: TComVUI() : m_aspectRatioInfoPresentFlag (false) //TODO: This initialiser list contains magic numbers , m_aspectRatioIdc (0) , m_sarWidth (0) , m_sarHeight (0) , m_overscanInfoPresentFlag (false) , m_overscanAppropriateFlag (false) , m_videoSignalTypePresentFlag (false) , m_videoFormat (5) , m_videoFullRangeFlag (false) , m_colourDescriptionPresentFlag (false) , m_colourPrimaries (2) , m_transferCharacteristics (2) , m_matrixCoefficients (2) , m_chromaLocInfoPresentFlag (false) , m_chromaSampleLocTypeTopField (0) , m_chromaSampleLocTypeBottomField (0) , m_neutralChromaIndicationFlag (false) , m_fieldSeqFlag (false) , m_frameFieldInfoPresentFlag (false) , m_hrdParametersPresentFlag (false) , m_bitstreamRestrictionFlag (false) , m_tilesFixedStructureFlag (false) , m_motionVectorsOverPicBoundariesFlag(true) , m_restrictedRefPicListsFlag (1) , m_minSpatialSegmentationIdc (0) , m_maxBytesPerPicDenom (2) , m_maxBitsPerMinCuDenom (1) , m_log2MaxMvLengthHorizontal (15) , m_log2MaxMvLengthVertical (15) {} virtual ~TComVUI() {} Bool getAspectRatioInfoPresentFlag() const { return m_aspectRatioInfoPresentFlag; } Void setAspectRatioInfoPresentFlag(Bool i) { m_aspectRatioInfoPresentFlag = i; } Int getAspectRatioIdc() const { return m_aspectRatioIdc; } Void setAspectRatioIdc(Int i) { m_aspectRatioIdc = i; } Int getSarWidth() const { return m_sarWidth; } Void setSarWidth(Int i) { m_sarWidth = i; } Int getSarHeight() const { return m_sarHeight; } Void setSarHeight(Int i) { m_sarHeight = i; } Bool getOverscanInfoPresentFlag() const { return m_overscanInfoPresentFlag; } Void setOverscanInfoPresentFlag(Bool i) { m_overscanInfoPresentFlag = i; } Bool getOverscanAppropriateFlag() const { return m_overscanAppropriateFlag; } Void setOverscanAppropriateFlag(Bool i) { m_overscanAppropriateFlag = i; } Bool getVideoSignalTypePresentFlag() const { return m_videoSignalTypePresentFlag; } Void setVideoSignalTypePresentFlag(Bool i) { m_videoSignalTypePresentFlag = i; } Int getVideoFormat() const { return m_videoFormat; } Void setVideoFormat(Int i) { m_videoFormat = i; } Bool getVideoFullRangeFlag() const { return m_videoFullRangeFlag; } Void setVideoFullRangeFlag(Bool i) { m_videoFullRangeFlag = i; } Bool getColourDescriptionPresentFlag() const { return m_colourDescriptionPresentFlag; } Void setColourDescriptionPresentFlag(Bool i) { m_colourDescriptionPresentFlag = i; } Int getColourPrimaries() const { return m_colourPrimaries; } Void setColourPrimaries(Int i) { m_colourPrimaries = i; } Int getTransferCharacteristics() const { return m_transferCharacteristics; } Void setTransferCharacteristics(Int i) { m_transferCharacteristics = i; } Int getMatrixCoefficients() const { return m_matrixCoefficients; } Void setMatrixCoefficients(Int i) { m_matrixCoefficients = i; } Bool getChromaLocInfoPresentFlag() const { return m_chromaLocInfoPresentFlag; } Void setChromaLocInfoPresentFlag(Bool i) { m_chromaLocInfoPresentFlag = i; } Int getChromaSampleLocTypeTopField() const { return m_chromaSampleLocTypeTopField; } Void setChromaSampleLocTypeTopField(Int i) { m_chromaSampleLocTypeTopField = i; } Int getChromaSampleLocTypeBottomField() const { return m_chromaSampleLocTypeBottomField; } Void setChromaSampleLocTypeBottomField(Int i) { m_chromaSampleLocTypeBottomField = i; } Bool getNeutralChromaIndicationFlag() const { return m_neutralChromaIndicationFlag; } Void setNeutralChromaIndicationFlag(Bool i) { m_neutralChromaIndicationFlag = i; } Bool getFieldSeqFlag() const { return m_fieldSeqFlag; } Void setFieldSeqFlag(Bool i) { m_fieldSeqFlag = i; } Bool getFrameFieldInfoPresentFlag() const { return m_frameFieldInfoPresentFlag; } Void setFrameFieldInfoPresentFlag(Bool i) { m_frameFieldInfoPresentFlag = i; } Window& getDefaultDisplayWindow() { return m_defaultDisplayWindow; } const Window& getDefaultDisplayWindow() const { return m_defaultDisplayWindow; } Void setDefaultDisplayWindow(Window& defaultDisplayWindow ) { m_defaultDisplayWindow = defaultDisplayWindow; } Bool getHrdParametersPresentFlag() const { return m_hrdParametersPresentFlag; } Void setHrdParametersPresentFlag(Bool i) { m_hrdParametersPresentFlag = i; } Bool getBitstreamRestrictionFlag() const { return m_bitstreamRestrictionFlag; } Void setBitstreamRestrictionFlag(Bool i) { m_bitstreamRestrictionFlag = i; } Bool getTilesFixedStructureFlag() const { return m_tilesFixedStructureFlag; } Void setTilesFixedStructureFlag(Bool i) { m_tilesFixedStructureFlag = i; } Bool getMotionVectorsOverPicBoundariesFlag() const { return m_motionVectorsOverPicBoundariesFlag; } Void setMotionVectorsOverPicBoundariesFlag(Bool i) { m_motionVectorsOverPicBoundariesFlag = i; } Bool getRestrictedRefPicListsFlag() const { return m_restrictedRefPicListsFlag; } Void setRestrictedRefPicListsFlag(Bool b) { m_restrictedRefPicListsFlag = b; } Int getMinSpatialSegmentationIdc() const { return m_minSpatialSegmentationIdc; } Void setMinSpatialSegmentationIdc(Int i) { m_minSpatialSegmentationIdc = i; } Int getMaxBytesPerPicDenom() const { return m_maxBytesPerPicDenom; } Void setMaxBytesPerPicDenom(Int i) { m_maxBytesPerPicDenom = i; } Int getMaxBitsPerMinCuDenom() const { return m_maxBitsPerMinCuDenom; } Void setMaxBitsPerMinCuDenom(Int i) { m_maxBitsPerMinCuDenom = i; } Int getLog2MaxMvLengthHorizontal() const { return m_log2MaxMvLengthHorizontal; } Void setLog2MaxMvLengthHorizontal(Int i) { m_log2MaxMvLengthHorizontal = i; } Int getLog2MaxMvLengthVertical() const { return m_log2MaxMvLengthVertical; } Void setLog2MaxMvLengthVertical(Int i) { m_log2MaxMvLengthVertical = i; } TComHRD* getHrdParameters() { return &m_hrdParameters; } const TComHRD* getHrdParameters() const { return &m_hrdParameters; } TimingInfo* getTimingInfo() { return &m_timingInfo; } const TimingInfo* getTimingInfo() const { return &m_timingInfo; } }; /// SPS RExt class class TComSPSRExt // Names aligned to text specification { private: Bool m_transformSkipRotationEnabledFlag; Bool m_transformSkipContextEnabledFlag; Bool m_rdpcmEnabledFlag[NUMBER_OF_RDPCM_SIGNALLING_MODES]; Bool m_extendedPrecisionProcessingFlag; Bool m_intraSmoothingDisabledFlag; Bool m_highPrecisionOffsetsEnabledFlag; Bool m_persistentRiceAdaptationEnabledFlag; Bool m_cabacBypassAlignmentEnabledFlag; public: TComSPSRExt(); Bool settingsDifferFromDefaults() const { return getTransformSkipRotationEnabledFlag() || getTransformSkipContextEnabledFlag() || getRdpcmEnabledFlag(RDPCM_SIGNAL_IMPLICIT) || getRdpcmEnabledFlag(RDPCM_SIGNAL_EXPLICIT) || getExtendedPrecisionProcessingFlag() || getIntraSmoothingDisabledFlag() || getHighPrecisionOffsetsEnabledFlag() || getPersistentRiceAdaptationEnabledFlag() || getCabacBypassAlignmentEnabledFlag(); } Bool getTransformSkipRotationEnabledFlag() const { return m_transformSkipRotationEnabledFlag; } Void setTransformSkipRotationEnabledFlag(const Bool value) { m_transformSkipRotationEnabledFlag = value; } Bool getTransformSkipContextEnabledFlag() const { return m_transformSkipContextEnabledFlag; } Void setTransformSkipContextEnabledFlag(const Bool value) { m_transformSkipContextEnabledFlag = value; } Bool getRdpcmEnabledFlag(const RDPCMSignallingMode signallingMode) const { return m_rdpcmEnabledFlag[signallingMode]; } Void setRdpcmEnabledFlag(const RDPCMSignallingMode signallingMode, const Bool value) { m_rdpcmEnabledFlag[signallingMode] = value; } Bool getExtendedPrecisionProcessingFlag() const { return m_extendedPrecisionProcessingFlag; } Void setExtendedPrecisionProcessingFlag(Bool value) { m_extendedPrecisionProcessingFlag = value; } Bool getIntraSmoothingDisabledFlag() const { return m_intraSmoothingDisabledFlag; } Void setIntraSmoothingDisabledFlag(Bool bValue) { m_intraSmoothingDisabledFlag=bValue; } Bool getHighPrecisionOffsetsEnabledFlag() const { return m_highPrecisionOffsetsEnabledFlag; } Void setHighPrecisionOffsetsEnabledFlag(Bool value) { m_highPrecisionOffsetsEnabledFlag = value; } Bool getPersistentRiceAdaptationEnabledFlag() const { return m_persistentRiceAdaptationEnabledFlag; } Void setPersistentRiceAdaptationEnabledFlag(const Bool value) { m_persistentRiceAdaptationEnabledFlag = value; } Bool getCabacBypassAlignmentEnabledFlag() const { return m_cabacBypassAlignmentEnabledFlag; } Void setCabacBypassAlignmentEnabledFlag(const Bool value) { m_cabacBypassAlignmentEnabledFlag = value; } }; /// SPS class class TComSPS { private: Int m_SPSId; Int m_VPSId; ChromaFormat m_chromaFormatIdc; UInt m_uiMaxTLayers; // maximum number of temporal layers // Structure UInt m_picWidthInLumaSamples; UInt m_picHeightInLumaSamples; Int m_log2MinCodingBlockSize; Int m_log2DiffMaxMinCodingBlockSize; UInt m_uiMaxCUWidth; UInt m_uiMaxCUHeight; UInt m_uiMaxTotalCUDepth; ///< Total CU depth, relative to the smallest possible transform block size. Window m_conformanceWindow; TComRPSList m_RPSList; Bool m_bLongTermRefsPresent; Bool m_SPSTemporalMVPEnabledFlag; Int m_numReorderPics[MAX_TLAYER]; // Tool list UInt m_uiQuadtreeTULog2MaxSize; UInt m_uiQuadtreeTULog2MinSize; UInt m_uiQuadtreeTUMaxDepthInter; UInt m_uiQuadtreeTUMaxDepthIntra; Bool m_usePCM; UInt m_pcmLog2MaxSize; UInt m_uiPCMLog2MinSize; Bool m_useAMP; // Parameter BitDepths m_bitDepths; Int m_qpBDOffset[MAX_NUM_CHANNEL_TYPE]; Int m_pcmBitDepths[MAX_NUM_CHANNEL_TYPE]; Bool m_bPCMFilterDisableFlag; UInt m_uiBitsForPOC; UInt m_numLongTermRefPicSPS; UInt m_ltRefPicPocLsbSps[MAX_NUM_LONG_TERM_REF_PICS]; Bool m_usedByCurrPicLtSPSFlag[MAX_NUM_LONG_TERM_REF_PICS]; // Max physical transform size UInt m_uiMaxTrSize; Bool m_bUseSAO; Bool m_bTemporalIdNestingFlag; // temporal_id_nesting_flag Bool m_scalingListEnabledFlag; Bool m_scalingListPresentFlag; TComScalingList m_scalingList; UInt m_uiMaxDecPicBuffering[MAX_TLAYER]; UInt m_uiMaxLatencyIncreasePlus1[MAX_TLAYER]; Bool m_useStrongIntraSmoothing; Bool m_vuiParametersPresentFlag; TComVUI m_vuiParameters; TComSPSRExt m_spsRangeExtension; static const Int m_winUnitX[NUM_CHROMA_FORMAT]; static const Int m_winUnitY[NUM_CHROMA_FORMAT]; TComPTL m_pcPTL; #if O0043_BEST_EFFORT_DECODING UInt m_forceDecodeBitDepth; // 0 = do not force the decoder's bit depth, other = force the decoder's bit depth to this value (best effort decoding) #endif public: TComSPS(); virtual ~TComSPS(); #if O0043_BEST_EFFORT_DECODING Void setForceDecodeBitDepth(UInt bitDepth) { m_forceDecodeBitDepth = bitDepth; } UInt getForceDecodeBitDepth() const { return m_forceDecodeBitDepth; } #endif Int getVPSId() const { return m_VPSId; } Void setVPSId(Int i) { m_VPSId = i; } Int getSPSId() const { return m_SPSId; } Void setSPSId(Int i) { m_SPSId = i; } ChromaFormat getChromaFormatIdc () const { return m_chromaFormatIdc; } Void setChromaFormatIdc (ChromaFormat i) { m_chromaFormatIdc = i; } static Int getWinUnitX (Int chromaFormatIdc) { assert (chromaFormatIdc >= 0 && chromaFormatIdc < NUM_CHROMA_FORMAT); return m_winUnitX[chromaFormatIdc]; } static Int getWinUnitY (Int chromaFormatIdc) { assert (chromaFormatIdc >= 0 && chromaFormatIdc < NUM_CHROMA_FORMAT); return m_winUnitY[chromaFormatIdc]; } // structure Void setPicWidthInLumaSamples( UInt u ) { m_picWidthInLumaSamples = u; } UInt getPicWidthInLumaSamples() const { return m_picWidthInLumaSamples; } Void setPicHeightInLumaSamples( UInt u ) { m_picHeightInLumaSamples = u; } UInt getPicHeightInLumaSamples() const { return m_picHeightInLumaSamples; } Window& getConformanceWindow() { return m_conformanceWindow; } const Window& getConformanceWindow() const { return m_conformanceWindow; } Void setConformanceWindow(Window& conformanceWindow ) { m_conformanceWindow = conformanceWindow; } UInt getNumLongTermRefPicSPS() const { return m_numLongTermRefPicSPS; } Void setNumLongTermRefPicSPS(UInt val) { m_numLongTermRefPicSPS = val; } UInt getLtRefPicPocLsbSps(UInt index) const { assert( index < MAX_NUM_LONG_TERM_REF_PICS ); return m_ltRefPicPocLsbSps[index]; } Void setLtRefPicPocLsbSps(UInt index, UInt val) { assert( index < MAX_NUM_LONG_TERM_REF_PICS ); m_ltRefPicPocLsbSps[index] = val; } Bool getUsedByCurrPicLtSPSFlag(Int i) const { assert( i < MAX_NUM_LONG_TERM_REF_PICS ); return m_usedByCurrPicLtSPSFlag[i]; } Void setUsedByCurrPicLtSPSFlag(Int i, Bool x) { assert( i < MAX_NUM_LONG_TERM_REF_PICS ); m_usedByCurrPicLtSPSFlag[i] = x; } Int getLog2MinCodingBlockSize() const { return m_log2MinCodingBlockSize; } Void setLog2MinCodingBlockSize(Int val) { m_log2MinCodingBlockSize = val; } Int getLog2DiffMaxMinCodingBlockSize() const { return m_log2DiffMaxMinCodingBlockSize; } Void setLog2DiffMaxMinCodingBlockSize(Int val) { m_log2DiffMaxMinCodingBlockSize = val; } Void setMaxCUWidth( UInt u ) { m_uiMaxCUWidth = u; } UInt getMaxCUWidth() const { return m_uiMaxCUWidth; } Void setMaxCUHeight( UInt u ) { m_uiMaxCUHeight = u; } UInt getMaxCUHeight() const { return m_uiMaxCUHeight; } Void setMaxTotalCUDepth( UInt u ) { m_uiMaxTotalCUDepth = u; } UInt getMaxTotalCUDepth() const { return m_uiMaxTotalCUDepth; } Void setUsePCM( Bool b ) { m_usePCM = b; } Bool getUsePCM() const { return m_usePCM; } Void setPCMLog2MaxSize( UInt u ) { m_pcmLog2MaxSize = u; } UInt getPCMLog2MaxSize() const { return m_pcmLog2MaxSize; } Void setPCMLog2MinSize( UInt u ) { m_uiPCMLog2MinSize = u; } UInt getPCMLog2MinSize() const { return m_uiPCMLog2MinSize; } Void setBitsForPOC( UInt u ) { m_uiBitsForPOC = u; } UInt getBitsForPOC() const { return m_uiBitsForPOC; } Bool getUseAMP() const { return m_useAMP; } Void setUseAMP( Bool b ) { m_useAMP = b; } Void setQuadtreeTULog2MaxSize( UInt u ) { m_uiQuadtreeTULog2MaxSize = u; } UInt getQuadtreeTULog2MaxSize() const { return m_uiQuadtreeTULog2MaxSize; } Void setQuadtreeTULog2MinSize( UInt u ) { m_uiQuadtreeTULog2MinSize = u; } UInt getQuadtreeTULog2MinSize() const { return m_uiQuadtreeTULog2MinSize; } Void setQuadtreeTUMaxDepthInter( UInt u ) { m_uiQuadtreeTUMaxDepthInter = u; } Void setQuadtreeTUMaxDepthIntra( UInt u ) { m_uiQuadtreeTUMaxDepthIntra = u; } UInt getQuadtreeTUMaxDepthInter() const { return m_uiQuadtreeTUMaxDepthInter; } UInt getQuadtreeTUMaxDepthIntra() const { return m_uiQuadtreeTUMaxDepthIntra; } Void setNumReorderPics(Int i, UInt tlayer) { m_numReorderPics[tlayer] = i; } Int getNumReorderPics(UInt tlayer) const { return m_numReorderPics[tlayer]; } Void createRPSList( Int numRPS ); const TComRPSList* getRPSList() const { return &m_RPSList; } TComRPSList* getRPSList() { return &m_RPSList; } Bool getLongTermRefsPresent() const { return m_bLongTermRefsPresent; } Void setLongTermRefsPresent(Bool b) { m_bLongTermRefsPresent=b; } Bool getSPSTemporalMVPEnabledFlag() const { return m_SPSTemporalMVPEnabledFlag; } Void setSPSTemporalMVPEnabledFlag(Bool b) { m_SPSTemporalMVPEnabledFlag=b; } // physical transform Void setMaxTrSize( UInt u ) { m_uiMaxTrSize = u; } UInt getMaxTrSize() const { return m_uiMaxTrSize; } // Bit-depth Int getBitDepth(ChannelType type) const { return m_bitDepths.recon[type]; } Void setBitDepth(ChannelType type, Int u ) { m_bitDepths.recon[type] = u; } #if O0043_BEST_EFFORT_DECODING Int getStreamBitDepth(ChannelType type) const { return m_bitDepths.stream[type]; } Void setStreamBitDepth(ChannelType type, Int u ) { m_bitDepths.stream[type] = u; } #endif const BitDepths& getBitDepths() const { return m_bitDepths; } Int getMaxLog2TrDynamicRange(ChannelType channelType) const { return getSpsRangeExtension().getExtendedPrecisionProcessingFlag() ? std::max(15, Int(m_bitDepths.recon[channelType] + 6)) : 15; } Int getDifferentialLumaChromaBitDepth() const { return Int(m_bitDepths.recon[CHANNEL_TYPE_LUMA]) - Int(m_bitDepths.recon[CHANNEL_TYPE_CHROMA]); } Int getQpBDOffset(ChannelType type) const { return m_qpBDOffset[type]; } Void setQpBDOffset(ChannelType type, Int i) { m_qpBDOffset[type] = i; } Void setUseSAO(Bool bVal) { m_bUseSAO = bVal; } Bool getUseSAO() const { return m_bUseSAO; } UInt getMaxTLayers() const { return m_uiMaxTLayers; } Void setMaxTLayers( UInt uiMaxTLayers ) { assert( uiMaxTLayers <= MAX_TLAYER ); m_uiMaxTLayers = uiMaxTLayers; } Bool getTemporalIdNestingFlag() const { return m_bTemporalIdNestingFlag; } Void setTemporalIdNestingFlag( Bool bValue ) { m_bTemporalIdNestingFlag = bValue; } UInt getPCMBitDepth(ChannelType type) const { return m_pcmBitDepths[type]; } Void setPCMBitDepth(ChannelType type, UInt u) { m_pcmBitDepths[type] = u; } Void setPCMFilterDisableFlag( Bool bValue ) { m_bPCMFilterDisableFlag = bValue; } Bool getPCMFilterDisableFlag() const { return m_bPCMFilterDisableFlag; } Bool getScalingListFlag() const { return m_scalingListEnabledFlag; } Void setScalingListFlag( Bool b ) { m_scalingListEnabledFlag = b; } Bool getScalingListPresentFlag() const { return m_scalingListPresentFlag; } Void setScalingListPresentFlag( Bool b ) { m_scalingListPresentFlag = b; } TComScalingList& getScalingList() { return m_scalingList; } const TComScalingList& getScalingList() const { return m_scalingList; } UInt getMaxDecPicBuffering(UInt tlayer) const { return m_uiMaxDecPicBuffering[tlayer]; } Void setMaxDecPicBuffering( UInt ui, UInt tlayer ) { assert(tlayer < MAX_TLAYER); m_uiMaxDecPicBuffering[tlayer] = ui; } UInt getMaxLatencyIncreasePlus1(UInt tlayer) const { return m_uiMaxLatencyIncreasePlus1[tlayer]; } Void setMaxLatencyIncreasePlus1( UInt ui , UInt tlayer) { m_uiMaxLatencyIncreasePlus1[tlayer] = ui; } Void setUseStrongIntraSmoothing(Bool bVal) { m_useStrongIntraSmoothing = bVal; } Bool getUseStrongIntraSmoothing() const { return m_useStrongIntraSmoothing; } Bool getVuiParametersPresentFlag() const { return m_vuiParametersPresentFlag; } Void setVuiParametersPresentFlag(Bool b) { m_vuiParametersPresentFlag = b; } TComVUI* getVuiParameters() { return &m_vuiParameters; } const TComVUI* getVuiParameters() const { return &m_vuiParameters; } const TComPTL* getPTL() const { return &m_pcPTL; } TComPTL* getPTL() { return &m_pcPTL; } const TComSPSRExt& getSpsRangeExtension() const { return m_spsRangeExtension; } TComSPSRExt& getSpsRangeExtension() { return m_spsRangeExtension; } }; /// Reference Picture Lists class class TComRefPicListModification { private: Bool m_refPicListModificationFlagL0; Bool m_refPicListModificationFlagL1; UInt m_RefPicSetIdxL0[REF_PIC_LIST_NUM_IDX]; UInt m_RefPicSetIdxL1[REF_PIC_LIST_NUM_IDX]; public: TComRefPicListModification(); virtual ~TComRefPicListModification(); Bool getRefPicListModificationFlagL0() const { return m_refPicListModificationFlagL0; } Void setRefPicListModificationFlagL0(Bool flag) { m_refPicListModificationFlagL0 = flag; } Bool getRefPicListModificationFlagL1() const { return m_refPicListModificationFlagL1; } Void setRefPicListModificationFlagL1(Bool flag) { m_refPicListModificationFlagL1 = flag; } UInt getRefPicSetIdxL0(UInt idx) const { assert(idx0; } Int getChromaQpOffsetListLen() const { return m_chromaQpOffsetListLen; } const ChromaQpAdj& getChromaQpOffsetListEntry( Int cuChromaQpOffsetIdxPlus1 ) const { assert(cuChromaQpOffsetIdxPlus1 < m_chromaQpOffsetListLen+1); return m_ChromaQpAdjTableIncludingNullEntry[cuChromaQpOffsetIdxPlus1]; // Array includes entry [0] for the null offset used when cu_chroma_qp_offset_flag=0, and entries [cu_chroma_qp_offset_idx+1...] otherwise } Void setChromaQpOffsetListEntry( Int cuChromaQpOffsetIdxPlus1, Int cbOffset, Int crOffset ) { assert (cuChromaQpOffsetIdxPlus1 != 0 && cuChromaQpOffsetIdxPlus1 <= MAX_QP_OFFSET_LIST_SIZE); m_ChromaQpAdjTableIncludingNullEntry[cuChromaQpOffsetIdxPlus1].u.comp.CbOffset = cbOffset; // Array includes entry [0] for the null offset used when cu_chroma_qp_offset_flag=0, and entries [cu_chroma_qp_offset_idx+1...] otherwise m_ChromaQpAdjTableIncludingNullEntry[cuChromaQpOffsetIdxPlus1].u.comp.CrOffset = crOffset; m_chromaQpOffsetListLen = max(m_chromaQpOffsetListLen, cuChromaQpOffsetIdxPlus1); } // Now: getPpsRangeExtension().getLog2SaoOffsetScale and getPpsRangeExtension().setLog2SaoOffsetScale UInt getLog2SaoOffsetScale(ChannelType type) const { return m_log2SaoOffsetScale[type]; } Void setLog2SaoOffsetScale(ChannelType type, UInt uiBitShift) { m_log2SaoOffsetScale[type] = uiBitShift; } }; /// PPS class class TComPPS { private: Int m_PPSId; // pic_parameter_set_id Int m_SPSId; // seq_parameter_set_id Int m_picInitQPMinus26; Bool m_useDQP; Bool m_bConstrainedIntraPred; // constrained_intra_pred_flag Bool m_bSliceChromaQpFlag; // slicelevel_chroma_qp_flag // access channel UInt m_uiMaxCuDQPDepth; Int m_chromaCbQpOffset; Int m_chromaCrQpOffset; UInt m_numRefIdxL0DefaultActive; UInt m_numRefIdxL1DefaultActive; Bool m_bUseWeightPred; //!< Use of Weighting Prediction (P_SLICE) Bool m_useWeightedBiPred; //!< Use of Weighting Bi-Prediction (B_SLICE) Bool m_OutputFlagPresentFlag; //!< Indicates the presence of output_flag in slice header Bool m_TransquantBypassEnabledFlag; //!< Indicates presence of cu_transquant_bypass_flag in CUs. Bool m_useTransformSkip; Bool m_dependentSliceSegmentsEnabledFlag; //!< Indicates the presence of dependent slices Bool m_tilesEnabledFlag; //!< Indicates the presence of tiles Bool m_entropyCodingSyncEnabledFlag; //!< Indicates the presence of wavefronts Bool m_loopFilterAcrossTilesEnabledFlag; Bool m_uniformSpacingFlag; Int m_numTileColumnsMinus1; Int m_numTileRowsMinus1; std::vector m_tileColumnWidth; std::vector m_tileRowHeight; Bool m_signDataHidingEnabledFlag; Bool m_cabacInitPresentFlag; Bool m_sliceHeaderExtensionPresentFlag; Bool m_loopFilterAcrossSlicesEnabledFlag; Bool m_deblockingFilterControlPresentFlag; Bool m_deblockingFilterOverrideEnabledFlag; Bool m_ppsDeblockingFilterDisabledFlag; Int m_deblockingFilterBetaOffsetDiv2; //< beta offset for deblocking filter Int m_deblockingFilterTcOffsetDiv2; //< tc offset for deblocking filter Bool m_scalingListPresentFlag; TComScalingList m_scalingList; //!< ScalingList class Bool m_listsModificationPresentFlag; UInt m_log2ParallelMergeLevelMinus2; Int m_numExtraSliceHeaderBits; TComPPSRExt m_ppsRangeExtension; public: TComPPS(); virtual ~TComPPS(); Int getPPSId() const { return m_PPSId; } Void setPPSId(Int i) { m_PPSId = i; } Int getSPSId() const { return m_SPSId; } Void setSPSId(Int i) { m_SPSId = i; } Int getPicInitQPMinus26() const { return m_picInitQPMinus26; } Void setPicInitQPMinus26( Int i ) { m_picInitQPMinus26 = i; } Bool getUseDQP() const { return m_useDQP; } Void setUseDQP( Bool b ) { m_useDQP = b; } Bool getConstrainedIntraPred() const { return m_bConstrainedIntraPred; } Void setConstrainedIntraPred( Bool b ) { m_bConstrainedIntraPred = b; } Bool getSliceChromaQpFlag() const { return m_bSliceChromaQpFlag; } Void setSliceChromaQpFlag( Bool b ) { m_bSliceChromaQpFlag = b; } Void setMaxCuDQPDepth( UInt u ) { m_uiMaxCuDQPDepth = u; } UInt getMaxCuDQPDepth() const { return m_uiMaxCuDQPDepth; } Void setQpOffset(ComponentID compID, Int i ) { if (compID==COMPONENT_Cb) { m_chromaCbQpOffset = i; } else if (compID==COMPONENT_Cr) { m_chromaCrQpOffset = i; } else { assert(0); } } Int getQpOffset(ComponentID compID) const { return (compID==COMPONENT_Y) ? 0 : (compID==COMPONENT_Cb ? m_chromaCbQpOffset : m_chromaCrQpOffset ); } Void setNumRefIdxL0DefaultActive(UInt ui) { m_numRefIdxL0DefaultActive=ui; } UInt getNumRefIdxL0DefaultActive() const { return m_numRefIdxL0DefaultActive; } Void setNumRefIdxL1DefaultActive(UInt ui) { m_numRefIdxL1DefaultActive=ui; } UInt getNumRefIdxL1DefaultActive() const { return m_numRefIdxL1DefaultActive; } Bool getUseWP() const { return m_bUseWeightPred; } Bool getWPBiPred() const { return m_useWeightedBiPred; } Void setUseWP( Bool b ) { m_bUseWeightPred = b; } Void setWPBiPred( Bool b ) { m_useWeightedBiPred = b; } Void setOutputFlagPresentFlag( Bool b ) { m_OutputFlagPresentFlag = b; } Bool getOutputFlagPresentFlag() const { return m_OutputFlagPresentFlag; } Void setTransquantBypassEnabledFlag( Bool b ) { m_TransquantBypassEnabledFlag = b; } Bool getTransquantBypassEnabledFlag() const { return m_TransquantBypassEnabledFlag; } Bool getUseTransformSkip() const { return m_useTransformSkip; } Void setUseTransformSkip( Bool b ) { m_useTransformSkip = b; } Void setLoopFilterAcrossTilesEnabledFlag(Bool b) { m_loopFilterAcrossTilesEnabledFlag = b; } Bool getLoopFilterAcrossTilesEnabledFlag() const { return m_loopFilterAcrossTilesEnabledFlag; } Bool getDependentSliceSegmentsEnabledFlag() const { return m_dependentSliceSegmentsEnabledFlag; } Void setDependentSliceSegmentsEnabledFlag(Bool val) { m_dependentSliceSegmentsEnabledFlag = val; } Bool getEntropyCodingSyncEnabledFlag() const { return m_entropyCodingSyncEnabledFlag; } Void setEntropyCodingSyncEnabledFlag(Bool val) { m_entropyCodingSyncEnabledFlag = val; } Void setTilesEnabledFlag(Bool val) { m_tilesEnabledFlag = val; } Bool getTilesEnabledFlag() const { return m_tilesEnabledFlag; } Void setTileUniformSpacingFlag(Bool b) { m_uniformSpacingFlag = b; } Bool getTileUniformSpacingFlag() const { return m_uniformSpacingFlag; } Void setNumTileColumnsMinus1(Int i) { m_numTileColumnsMinus1 = i; } Int getNumTileColumnsMinus1() const { return m_numTileColumnsMinus1; } Void setTileColumnWidth(const std::vector& columnWidth ) { m_tileColumnWidth = columnWidth; } UInt getTileColumnWidth(UInt columnIdx) const { return m_tileColumnWidth[columnIdx]; } Void setNumTileRowsMinus1(Int i) { m_numTileRowsMinus1 = i; } Int getNumTileRowsMinus1() const { return m_numTileRowsMinus1; } Void setTileRowHeight(const std::vector& rowHeight) { m_tileRowHeight = rowHeight; } UInt getTileRowHeight(UInt rowIdx) const { return m_tileRowHeight[rowIdx]; } Void setSignDataHidingEnabledFlag( Bool b ) { m_signDataHidingEnabledFlag = b; } Bool getSignDataHidingEnabledFlag() const { return m_signDataHidingEnabledFlag; } Void setCabacInitPresentFlag( Bool flag ) { m_cabacInitPresentFlag = flag; } Bool getCabacInitPresentFlag() const { return m_cabacInitPresentFlag; } Void setDeblockingFilterControlPresentFlag( Bool val ) { m_deblockingFilterControlPresentFlag = val; } Bool getDeblockingFilterControlPresentFlag() const { return m_deblockingFilterControlPresentFlag; } Void setDeblockingFilterOverrideEnabledFlag( Bool val ) { m_deblockingFilterOverrideEnabledFlag = val; } Bool getDeblockingFilterOverrideEnabledFlag() const { return m_deblockingFilterOverrideEnabledFlag; } Void setPPSDeblockingFilterDisabledFlag(Bool val) { m_ppsDeblockingFilterDisabledFlag = val; } //!< set offset for deblocking filter disabled Bool getPPSDeblockingFilterDisabledFlag() const { return m_ppsDeblockingFilterDisabledFlag; } //!< get offset for deblocking filter disabled Void setDeblockingFilterBetaOffsetDiv2(Int val) { m_deblockingFilterBetaOffsetDiv2 = val; } //!< set beta offset for deblocking filter Int getDeblockingFilterBetaOffsetDiv2() const { return m_deblockingFilterBetaOffsetDiv2; } //!< get beta offset for deblocking filter Void setDeblockingFilterTcOffsetDiv2(Int val) { m_deblockingFilterTcOffsetDiv2 = val; } //!< set tc offset for deblocking filter Int getDeblockingFilterTcOffsetDiv2() const { return m_deblockingFilterTcOffsetDiv2; } //!< get tc offset for deblocking filter Bool getScalingListPresentFlag() const { return m_scalingListPresentFlag; } Void setScalingListPresentFlag( Bool b ) { m_scalingListPresentFlag = b; } TComScalingList& getScalingList() { return m_scalingList; } const TComScalingList& getScalingList() const { return m_scalingList; } Bool getListsModificationPresentFlag() const { return m_listsModificationPresentFlag; } Void setListsModificationPresentFlag( Bool b ) { m_listsModificationPresentFlag = b; } UInt getLog2ParallelMergeLevelMinus2() const { return m_log2ParallelMergeLevelMinus2; } Void setLog2ParallelMergeLevelMinus2(UInt mrgLevel) { m_log2ParallelMergeLevelMinus2 = mrgLevel; } Int getNumExtraSliceHeaderBits() const { return m_numExtraSliceHeaderBits; } Void setNumExtraSliceHeaderBits(Int i) { m_numExtraSliceHeaderBits = i; } Void setLoopFilterAcrossSlicesEnabledFlag( Bool bValue ) { m_loopFilterAcrossSlicesEnabledFlag = bValue; } Bool getLoopFilterAcrossSlicesEnabledFlag() const { return m_loopFilterAcrossSlicesEnabledFlag; } Bool getSliceHeaderExtensionPresentFlag() const { return m_sliceHeaderExtensionPresentFlag; } Void setSliceHeaderExtensionPresentFlag(Bool val) { m_sliceHeaderExtensionPresentFlag = val; } const TComPPSRExt& getPpsRangeExtension() const { return m_ppsRangeExtension; } TComPPSRExt& getPpsRangeExtension() { return m_ppsRangeExtension; } }; struct WPScalingParam { // Explicit weighted prediction parameters parsed in slice header, // or Implicit weighted prediction parameters (8 bits depth values). Bool bPresentFlag; UInt uiLog2WeightDenom; Int iWeight; Int iOffset; // Weighted prediction scaling values built from above parameters (bitdepth scaled): Int w; Int o; Int offset; Int shift; Int round; }; struct WPACDCParam { Int64 iAC; Int64 iDC; }; /// slice header class class TComSlice { private: // Bitstream writing Bool m_saoEnabledFlag[MAX_NUM_CHANNEL_TYPE]; Int m_iPPSId; ///< picture parameter set ID Bool m_PicOutputFlag; ///< pic_output_flag Int m_iPOC; Int m_iLastIDR; Int m_iAssociatedIRAP; NalUnitType m_iAssociatedIRAPType; const TComReferencePictureSet* m_pRPS; //< pointer to RPS, either in the SPS or the local RPS in the same slice header TComReferencePictureSet m_localRPS; //< RPS when present in slice header Int m_rpsIdx; //< index of used RPS in the SPS or -1 for local RPS in the slice header TComRefPicListModification m_RefPicListModification; NalUnitType m_eNalUnitType; ///< Nal unit type for the slice SliceType m_eSliceType; Int m_iSliceQp; Bool m_dependentSliceSegmentFlag; #if ADAPTIVE_QP_SELECTION Int m_iSliceQpBase; #endif Bool m_ChromaQpAdjEnabled; Bool m_deblockingFilterDisable; Bool m_deblockingFilterOverrideFlag; //< offsets for deblocking filter inherit from PPS Int m_deblockingFilterBetaOffsetDiv2; //< beta offset for deblocking filter Int m_deblockingFilterTcOffsetDiv2; //< tc offset for deblocking filter Int m_list1IdxToList0Idx[MAX_NUM_REF]; Int m_aiNumRefIdx [NUM_REF_PIC_LIST_01]; // for multiple reference of current slice Bool m_bCheckLDC; // Data Int m_iSliceQpDelta; Int m_iSliceChromaQpDelta[MAX_NUM_COMPONENT]; TComPic* m_apcRefPicList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; Int m_aiRefPOCList [NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; Bool m_bIsUsedAsLongTerm[NUM_REF_PIC_LIST_01][MAX_NUM_REF+1]; Int m_iDepth; // referenced slice? Bool m_bRefenced; // access channel const TComVPS* m_pcVPS; const TComSPS* m_pcSPS; const TComPPS* m_pcPPS; TComPic* m_pcPic; Bool m_colFromL0Flag; // collocated picture from List0 flag Bool m_noOutputPriorPicsFlag; Bool m_noRaslOutputFlag; Bool m_handleCraAsBlaFlag; UInt m_colRefIdx; UInt m_maxNumMergeCand; Double m_lambdas[MAX_NUM_COMPONENT]; Bool m_abEqualRef [NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_REF]; UInt m_uiTLayer; Bool m_bTLayerSwitchingFlag; SliceConstraint m_sliceMode; UInt m_sliceArgument; UInt m_sliceCurStartCtuTsAddr; UInt m_sliceCurEndCtuTsAddr; UInt m_sliceIdx; SliceConstraint m_sliceSegmentMode; UInt m_sliceSegmentArgument; UInt m_sliceSegmentCurStartCtuTsAddr; UInt m_sliceSegmentCurEndCtuTsAddr; Bool m_nextSlice; Bool m_nextSliceSegment; UInt m_sliceBits; UInt m_sliceSegmentBits; Bool m_bFinalized; Bool m_bTestWeightPred; Bool m_bTestWeightBiPred; WPScalingParam m_weightPredTable[NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_COMPONENT]; // [REF_PIC_LIST_0 or REF_PIC_LIST_1][refIdx][0:Y, 1:U, 2:V] WPACDCParam m_weightACDCParam[MAX_NUM_COMPONENT]; std::vector m_substreamSizes; Bool m_cabacInitFlag; Bool m_bLMvdL1Zero; Bool m_temporalLayerNonReferenceFlag; Bool m_LFCrossSliceBoundaryFlag; Bool m_enableTMVPFlag; SliceType m_encCABACTableIdx; // Used to transmit table selection across slices. public: TComSlice(); virtual ~TComSlice(); Void initSlice(); Void setVPS( TComVPS* pcVPS ) { m_pcVPS = pcVPS; } const TComVPS* getVPS() const { return m_pcVPS; } Void setSPS( const TComSPS* pcSPS ) { m_pcSPS = pcSPS; } const TComSPS* getSPS() const { return m_pcSPS; } Void setPPS( const TComPPS* pcPPS ) { m_pcPPS = pcPPS; m_iPPSId = (pcPPS) ? pcPPS->getPPSId() : -1; } const TComPPS* getPPS() const { return m_pcPPS; } Void setPPSId( Int PPSId ) { m_iPPSId = PPSId; } Int getPPSId() const { return m_iPPSId; } Void setPicOutputFlag( Bool b ) { m_PicOutputFlag = b; } Bool getPicOutputFlag() const { return m_PicOutputFlag; } Void setSaoEnabledFlag(ChannelType chType, Bool s) {m_saoEnabledFlag[chType] =s; } Bool getSaoEnabledFlag(ChannelType chType) const { return m_saoEnabledFlag[chType]; } Void setRPS( const TComReferencePictureSet *pcRPS ) { m_pRPS = pcRPS; } const TComReferencePictureSet* getRPS() { return m_pRPS; } TComReferencePictureSet* getLocalRPS() { return &m_localRPS; } Void setRPSidx( Int rpsIdx ) { m_rpsIdx = rpsIdx; } Int getRPSidx() const { return m_rpsIdx; } TComRefPicListModification* getRefPicListModification() { return &m_RefPicListModification; } Void setLastIDR(Int iIDRPOC) { m_iLastIDR = iIDRPOC; } Int getLastIDR() const { return m_iLastIDR; } Void setAssociatedIRAPPOC(Int iAssociatedIRAPPOC) { m_iAssociatedIRAP = iAssociatedIRAPPOC; } Int getAssociatedIRAPPOC() const { return m_iAssociatedIRAP; } Void setAssociatedIRAPType(NalUnitType associatedIRAPType) { m_iAssociatedIRAPType = associatedIRAPType; } NalUnitType getAssociatedIRAPType() const { return m_iAssociatedIRAPType; } SliceType getSliceType() const { return m_eSliceType; } Int getPOC() const { return m_iPOC; } Int getSliceQp() const { return m_iSliceQp; } Bool getUseWeightedPrediction() const { return( (m_eSliceType==P_SLICE && testWeightPred()) || (m_eSliceType==B_SLICE && testWeightBiPred()) ); } Bool getDependentSliceSegmentFlag() const { return m_dependentSliceSegmentFlag; } Void setDependentSliceSegmentFlag(Bool val) { m_dependentSliceSegmentFlag = val; } #if ADAPTIVE_QP_SELECTION Int getSliceQpBase() const { return m_iSliceQpBase; } #endif Int getSliceQpDelta() const { return m_iSliceQpDelta; } Int getSliceChromaQpDelta(ComponentID compID) const { return isLuma(compID) ? 0 : m_iSliceChromaQpDelta[compID]; } Bool getUseChromaQpAdj() const { return m_ChromaQpAdjEnabled; } Bool getDeblockingFilterDisable() const { return m_deblockingFilterDisable; } Bool getDeblockingFilterOverrideFlag() const { return m_deblockingFilterOverrideFlag; } Int getDeblockingFilterBetaOffsetDiv2()const { return m_deblockingFilterBetaOffsetDiv2; } Int getDeblockingFilterTcOffsetDiv2() const { return m_deblockingFilterTcOffsetDiv2; } Int getNumRefIdx( RefPicList e ) const { return m_aiNumRefIdx[e]; } TComPic* getPic() { return m_pcPic; } const TComPic* getPic() const { return m_pcPic; } TComPic* getRefPic( RefPicList e, Int iRefIdx) { return m_apcRefPicList[e][iRefIdx]; } const TComPic* getRefPic( RefPicList e, Int iRefIdx) const { return m_apcRefPicList[e][iRefIdx]; } Int getRefPOC( RefPicList e, Int iRefIdx) const { return m_aiRefPOCList[e][iRefIdx]; } Int getDepth() const { return m_iDepth; } Bool getColFromL0Flag() const { return m_colFromL0Flag; } UInt getColRefIdx() const { return m_colRefIdx; } Void checkColRefIdx(UInt curSliceIdx, TComPic* pic); Bool getIsUsedAsLongTerm(Int i, Int j) const { return m_bIsUsedAsLongTerm[i][j]; } Void setIsUsedAsLongTerm(Int i, Int j, Bool value) { m_bIsUsedAsLongTerm[i][j] = value; } Bool getCheckLDC() const { return m_bCheckLDC; } Bool getMvdL1ZeroFlag() const { return m_bLMvdL1Zero; } Int getNumRpsCurrTempList() const; Int getList1IdxToList0Idx( Int list1Idx ) const { return m_list1IdxToList0Idx[list1Idx]; } Void setReferenced(Bool b) { m_bRefenced = b; } Bool isReferenced() const { return m_bRefenced; } Bool isReferenceNalu() const { return ((getNalUnitType() <= NAL_UNIT_RESERVED_VCL_R15) && (getNalUnitType()%2 != 0)) || ((getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP) && (getNalUnitType() <= NAL_UNIT_RESERVED_IRAP_VCL23) ); } Void setPOC( Int i ) { m_iPOC = i; } Void setNalUnitType( NalUnitType e ) { m_eNalUnitType = e; } NalUnitType getNalUnitType() const { return m_eNalUnitType; } Bool getRapPicFlag() const; Bool getIdrPicFlag() const { return getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP; } Bool isIRAP() const { return (getNalUnitType() >= 16) && (getNalUnitType() <= 23); } Void checkCRA(const TComReferencePictureSet *pReferencePictureSet, Int& pocCRA, NalUnitType& associatedIRAPType, TComList& rcListPic); Void decodingRefreshMarking(Int& pocCRA, Bool& bRefreshPending, TComList& rcListPic, const bool bEfficientFieldIRAPEnabled); Void setSliceType( SliceType e ) { m_eSliceType = e; } Void setSliceQp( Int i ) { m_iSliceQp = i; } #if ADAPTIVE_QP_SELECTION Void setSliceQpBase( Int i ) { m_iSliceQpBase = i; } #endif Void setSliceQpDelta( Int i ) { m_iSliceQpDelta = i; } Void setSliceChromaQpDelta( ComponentID compID, Int i ) { m_iSliceChromaQpDelta[compID] = isLuma(compID) ? 0 : i; } Void setUseChromaQpAdj( Bool b ) { m_ChromaQpAdjEnabled = b; } Void setDeblockingFilterDisable( Bool b ) { m_deblockingFilterDisable= b; } Void setDeblockingFilterOverrideFlag( Bool b ) { m_deblockingFilterOverrideFlag = b; } Void setDeblockingFilterBetaOffsetDiv2( Int i ) { m_deblockingFilterBetaOffsetDiv2 = i; } Void setDeblockingFilterTcOffsetDiv2( Int i ) { m_deblockingFilterTcOffsetDiv2 = i; } Void setRefPic( TComPic* p, RefPicList e, Int iRefIdx ) { m_apcRefPicList[e][iRefIdx] = p; } Void setRefPOC( Int i, RefPicList e, Int iRefIdx ) { m_aiRefPOCList[e][iRefIdx] = i; } Void setNumRefIdx( RefPicList e, Int i ) { m_aiNumRefIdx[e] = i; } Void setPic( TComPic* p ) { m_pcPic = p; } Void setDepth( Int iDepth ) { m_iDepth = iDepth; } Void setRefPicList( TComList& rcListPic, Bool checkNumPocTotalCurr = false ); Void setRefPOCList(); Void setColFromL0Flag( Bool colFromL0 ) { m_colFromL0Flag = colFromL0; } Void setColRefIdx( UInt refIdx) { m_colRefIdx = refIdx; } Void setCheckLDC( Bool b ) { m_bCheckLDC = b; } Void setMvdL1ZeroFlag( Bool b) { m_bLMvdL1Zero = b; } Bool isIntra() const { return m_eSliceType == I_SLICE; } Bool isInterB() const { return m_eSliceType == B_SLICE; } Bool isInterP() const { return m_eSliceType == P_SLICE; } Void setLambdas( const Double lambdas[MAX_NUM_COMPONENT] ) { for (Int component = 0; component < MAX_NUM_COMPONENT; component++) m_lambdas[component] = lambdas[component]; } const Double* getLambdas() const { return m_lambdas; } Void initEqualRef(); Bool isEqualRef( RefPicList e, Int iRefIdx1, Int iRefIdx2 ) { assert(e& rcListPic ); Void setList1IdxToList0Idx(); UInt getTLayer() const { return m_uiTLayer; } Void setTLayer( UInt uiTLayer ) { m_uiTLayer = uiTLayer; } Void setTLayerInfo( UInt uiTLayer ); Void decodingMarking( TComList& rcListPic, Int iGOPSIze, Int& iMaxRefPicNum ); Void checkLeadingPictureRestrictions( TComList& rcListPic ); Void applyReferencePictureSet( TComList& rcListPic, const TComReferencePictureSet *RPSList); Bool isTemporalLayerSwitchingPoint( TComList& rcListPic ); Bool isStepwiseTemporalLayerSwitchingPointCandidate( TComList& rcListPic ); Int checkThatAllRefPicsAreAvailable( TComList& rcListPic, const TComReferencePictureSet *pReferencePictureSet, Bool printErrors, Int pocRandomAccess = 0, Bool bUseRecoveryPoint = false); Void createExplicitReferencePictureSetFromReference( TComList& rcListPic, const TComReferencePictureSet *pReferencePictureSet, Bool isRAP, Int pocRandomAccess, Bool bUseRecoveryPoint, const Bool bEfficientFieldIRAPEnabled); Void setMaxNumMergeCand(UInt val ) { m_maxNumMergeCand = val; } UInt getMaxNumMergeCand() const { return m_maxNumMergeCand; } Void setNoOutputPriorPicsFlag( Bool val ) { m_noOutputPriorPicsFlag = val; } Bool getNoOutputPriorPicsFlag() const { return m_noOutputPriorPicsFlag; } Void setNoRaslOutputFlag( Bool val ) { m_noRaslOutputFlag = val; } Bool getNoRaslOutputFlag() const { return m_noRaslOutputFlag; } Void setHandleCraAsBlaFlag( Bool val ) { m_handleCraAsBlaFlag = val; } Bool getHandleCraAsBlaFlag() const { return m_handleCraAsBlaFlag; } Void setSliceMode( SliceConstraint mode ) { m_sliceMode = mode; } SliceConstraint getSliceMode() const { return m_sliceMode; } Void setSliceArgument( UInt uiArgument ) { m_sliceArgument = uiArgument; } UInt getSliceArgument() const { return m_sliceArgument; } Void setSliceCurStartCtuTsAddr( UInt ctuTsAddr ) { m_sliceCurStartCtuTsAddr = ctuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) UInt getSliceCurStartCtuTsAddr() const { return m_sliceCurStartCtuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) Void setSliceCurEndCtuTsAddr( UInt ctuTsAddr ) { m_sliceCurEndCtuTsAddr = ctuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) UInt getSliceCurEndCtuTsAddr() const { return m_sliceCurEndCtuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) Void setSliceIdx( UInt i) { m_sliceIdx = i; } UInt getSliceIdx() const { return m_sliceIdx; } Void copySliceInfo(TComSlice *pcSliceSrc); Void setSliceSegmentMode( SliceConstraint mode ) { m_sliceSegmentMode = mode; } SliceConstraint getSliceSegmentMode() const { return m_sliceSegmentMode; } Void setSliceSegmentArgument( UInt uiArgument ) { m_sliceSegmentArgument = uiArgument; } UInt getSliceSegmentArgument() const { return m_sliceSegmentArgument; } Void setSliceSegmentCurStartCtuTsAddr( UInt ctuTsAddr ) { m_sliceSegmentCurStartCtuTsAddr = ctuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) UInt getSliceSegmentCurStartCtuTsAddr() const { return m_sliceSegmentCurStartCtuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) Void setSliceSegmentCurEndCtuTsAddr( UInt ctuTsAddr ) { m_sliceSegmentCurEndCtuTsAddr = ctuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) UInt getSliceSegmentCurEndCtuTsAddr() const { return m_sliceSegmentCurEndCtuTsAddr; } // CTU Tile-scan address (as opposed to raster-scan) Void setSliceBits( UInt uiVal ) { m_sliceBits = uiVal; } UInt getSliceBits() const { return m_sliceBits; } Void setSliceSegmentBits( UInt uiVal ) { m_sliceSegmentBits = uiVal; } UInt getSliceSegmentBits() const { return m_sliceSegmentBits; } Void setFinalized( Bool uiVal ) { m_bFinalized = uiVal; } Bool getFinalized() const { return m_bFinalized; } Bool testWeightPred( ) const { return m_bTestWeightPred; } Void setTestWeightPred( Bool bValue ) { m_bTestWeightPred = bValue; } Bool testWeightBiPred( ) const { return m_bTestWeightBiPred; } Void setTestWeightBiPred( Bool bValue ) { m_bTestWeightBiPred = bValue; } Void setWpScaling( WPScalingParam wp[NUM_REF_PIC_LIST_01][MAX_NUM_REF][MAX_NUM_COMPONENT] ) { memcpy(m_weightPredTable, wp, sizeof(WPScalingParam)*NUM_REF_PIC_LIST_01*MAX_NUM_REF*MAX_NUM_COMPONENT); } Void getWpScaling( RefPicList e, Int iRefIdx, WPScalingParam *&wp); Void resetWpScaling(); Void initWpScaling(const TComSPS *sps); Void setWpAcDcParam( WPACDCParam wp[MAX_NUM_COMPONENT] ) { memcpy(m_weightACDCParam, wp, sizeof(WPACDCParam)*MAX_NUM_COMPONENT); } Void getWpAcDcParam( WPACDCParam *&wp ); Void initWpAcDcParam(); Void clearSubstreamSizes( ) { return m_substreamSizes.clear(); } UInt getNumberOfSubstreamSizes( ) { return (UInt) m_substreamSizes.size(); } Void addSubstreamSize( UInt size ) { m_substreamSizes.push_back(size); } UInt getSubstreamSize( Int idx ) { assert(idx& rcListPic, Int poc); TComPic* xGetLongTermRefPic(TComList& rcListPic, Int poc, Bool pocHasMsb); };// END CLASS DEFINITION TComSlice Void calculateParameterSetChangedFlag(Bool &bChanged, const std::vector *pOldData, const std::vector *pNewData); template class ParameterSetMap { public: template struct MapData { Bool bChanged; std::vector *pNaluData; // Can be null Tm* parameterSet; }; ParameterSetMap(Int maxId) :m_maxId (maxId) {} ~ParameterSetMap() { for (typename std::map >::iterator i = m_paramsetMap.begin(); i!= m_paramsetMap.end(); i++) { delete (*i).second.pNaluData; delete (*i).second.parameterSet; } } T *allocatePS(const Int psId) { assert ( psId < m_maxId ); if ( m_paramsetMap.find(psId) == m_paramsetMap.end() ) { m_paramsetMap[psId].bChanged = true; m_paramsetMap[psId].pNaluData=0; m_paramsetMap[psId].parameterSet = new T; setID(m_paramsetMap[psId].parameterSet, psId); } return m_paramsetMap[psId].parameterSet; } Void storePS(Int psId, T *ps, const std::vector *pNaluData) { assert ( psId < m_maxId ); if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { MapData &mapData=m_paramsetMap[psId]; // work out changed flag calculateParameterSetChangedFlag(mapData.bChanged, mapData.pNaluData, pNaluData); delete m_paramsetMap[psId].pNaluData; delete m_paramsetMap[psId].parameterSet; m_paramsetMap[psId].parameterSet = ps; } else { m_paramsetMap[psId].parameterSet = ps; m_paramsetMap[psId].bChanged = false; } if (pNaluData != 0) { m_paramsetMap[psId].pNaluData=new std::vector; *(m_paramsetMap[psId].pNaluData) = *pNaluData; } else { m_paramsetMap[psId].pNaluData=0; } } Void setChangedFlag(Int psId, Bool bChanged=true) { if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { m_paramsetMap[psId].bChanged=bChanged; } } Void clearChangedFlag(Int psId) { if ( m_paramsetMap.find(psId) != m_paramsetMap.end() ) { m_paramsetMap[psId].bChanged=false; } } Bool getChangedFlag(Int psId) const { const typename std::map >::const_iterator constit=m_paramsetMap.find(psId); if ( constit != m_paramsetMap.end() ) { return constit->second.bChanged; } return false; } T* getPS(Int psId) { typename std::map >::iterator it=m_paramsetMap.find(psId); return ( it == m_paramsetMap.end() ) ? NULL : (it)->second.parameterSet; } const T* getPS(Int psId) const { typename std::map >::const_iterator it=m_paramsetMap.find(psId); return ( it == m_paramsetMap.end() ) ? NULL : (it)->second.parameterSet; } T* getFirstPS() { return (m_paramsetMap.begin() == m_paramsetMap.end() ) ? NULL : m_paramsetMap.begin()->second.parameterSet; } private: std::map > m_paramsetMap; Int m_maxId; static Void setID(T* parameterSet, const Int psId); }; class ParameterSetManager { public: ParameterSetManager(); virtual ~ParameterSetManager(); //! store sequence parameter set and take ownership of it Void storeVPS(TComVPS *vps, const std::vector &naluData) { m_vpsMap.storePS( vps->getVPSId(), vps, &naluData); }; //! get pointer to existing video parameter set TComVPS* getVPS(Int vpsId) { return m_vpsMap.getPS(vpsId); }; Bool getVPSChangedFlag(Int vpsId) const { return m_vpsMap.getChangedFlag(vpsId); } Void clearVPSChangedFlag(Int vpsId) { m_vpsMap.clearChangedFlag(vpsId); } TComVPS* getFirstVPS() { return m_vpsMap.getFirstPS(); }; //! store sequence parameter set and take ownership of it Void storeSPS(TComSPS *sps, const std::vector &naluData) { m_spsMap.storePS( sps->getSPSId(), sps, &naluData); }; //! get pointer to existing sequence parameter set TComSPS* getSPS(Int spsId) { return m_spsMap.getPS(spsId); }; Bool getSPSChangedFlag(Int spsId) const { return m_spsMap.getChangedFlag(spsId); } Void clearSPSChangedFlag(Int spsId) { m_spsMap.clearChangedFlag(spsId); } TComSPS* getFirstSPS() { return m_spsMap.getFirstPS(); }; //! store picture parameter set and take ownership of it Void storePPS(TComPPS *pps, const std::vector &naluData) { m_ppsMap.storePS( pps->getPPSId(), pps, &naluData); }; //! get pointer to existing picture parameter set TComPPS* getPPS(Int ppsId) { return m_ppsMap.getPS(ppsId); }; Bool getPPSChangedFlag(Int ppsId) const { return m_ppsMap.getChangedFlag(ppsId); } Void clearPPSChangedFlag(Int ppsId) { m_ppsMap.clearChangedFlag(ppsId); } TComPPS* getFirstPPS() { return m_ppsMap.getFirstPS(); }; //! activate a SPS from a active parameter sets SEI message //! \returns true, if activation is successful // Bool activateSPSWithSEI(Int SPSId); //! activate a PPS and depending on isIDR parameter also SPS and VPS //! \returns true, if activation is successful Bool activatePPS(Int ppsId, Bool isIRAP); const TComVPS* getActiveVPS()const { return m_vpsMap.getPS(m_activeVPSId); }; const TComSPS* getActiveSPS()const { return m_spsMap.getPS(m_activeSPSId); }; protected: ParameterSetMap m_vpsMap; ParameterSetMap m_spsMap; ParameterSetMap m_ppsMap; Int m_activeVPSId; // -1 for nothing active Int m_activeSPSId; // -1 for nothing active }; //! \} #endif // __TCOMSLICE__ HM-HM-18.0/source/Lib/TLibCommon/TComTU.cpp000066400000000000000000000222341442026013100200740ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "TComTU.h" #include "TComRom.h" #include "TComDataCU.h" #include "TComPic.h" //---------------------------------------------------------------------------------------------------------------------- /*static*/ const UInt TComTU::NUMBER_OF_SECTIONS[TComTU::NUMBER_OF_SPLIT_MODES] = { 1, 2, 4 }; static const UInt partIdxStepShift [TComTU::NUMBER_OF_SPLIT_MODES] = { 0, 1, 2 }; //---------------------------------------------------------------------------------------------------------------------- TComTU::TComTU(TComDataCU *pcCU, const UInt absPartIdxCU, const UInt cuDepth, const UInt initTrDepthRelCU) : mChromaFormat(pcCU->getSlice()->getSPS()->getChromaFormatIdc()), mbProcessLastOfLevel(true), // does not matter. the top level is not 4 quadrants. mCuDepth(cuDepth), mSection(0), mSplitMode(DONT_SPLIT), mAbsPartIdxCU(absPartIdxCU), mAbsPartIdxTURelCU(0), mAbsPartIdxStep(pcCU->getPic()->getNumPartitionsInCtu() >> (pcCU->getDepth(absPartIdxCU)<<1)), mpcCU(pcCU), mLog2TrLumaSize(0), mpParent(NULL) { const TComSPS *pSPS=pcCU->getSlice()->getSPS(); mLog2TrLumaSize = g_aucConvertToBit[pSPS->getMaxCUWidth() >> (mCuDepth+initTrDepthRelCU)]+2; const UInt baseOffset444=pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight()*absPartIdxCU; for(UInt i=0; igetWidth( absPartIdxCU) >> csx) : 0; mRect[i].height = (i < getNumberValidComponents(mChromaFormat)) ? (pcCU->getHeight(absPartIdxCU) >> csy) : 0; mRect[i].x0=0; mRect[i].y0=0; mCodeAll[i]=true; mOffsets[i]=baseOffset444>>(csx+csy); } } TComTURecurse::TComTURecurse( TComDataCU *pcCU, const UInt absPartIdxCU) : TComTU(pcCU, absPartIdxCU, pcCU->getDepth(absPartIdxCU), 0) { } TComTU::TComTU(TComTU &parent, const Bool bProcessLastOfLevel, const TU_SPLIT_MODE splitMode, const Bool splitAtCurrentDepth, const ComponentID absPartIdxSourceComponent) : mChromaFormat(parent.mChromaFormat), mbProcessLastOfLevel(bProcessLastOfLevel), mCuDepth(parent.mCuDepth), mSection(0), mSplitMode(splitMode), mAbsPartIdxCU(parent.mAbsPartIdxCU), mAbsPartIdxTURelCU(parent.GetRelPartIdxTU(absPartIdxSourceComponent)), mAbsPartIdxStep(std::max(1, (parent.GetAbsPartIdxNumParts(absPartIdxSourceComponent) >> partIdxStepShift[splitMode]))), mpcCU(parent.mpcCU), mLog2TrLumaSize(parent.mLog2TrLumaSize - ((splitMode != QUAD_SPLIT) ? 0 : 1)), //no change in width for vertical split mpParent(&parent) { for(UInt i=0; i>1; mOffsets[i]=parent.mOffsets[i]; mCodeAll[i]=true; // The 2 TUs at this level is coded. mOrigWidth[i]=mRect[i].width; } return; } for(UInt i=0; i> 1); mRect[i].height= (parent.mRect[i].height>> 1); mRect[i].x0=parent.mRect[i].x0; mRect[i].y0=parent.mRect[i].y0; mOffsets[i]=parent.mOffsets[i]; if ((mRect[i].width < MIN_TU_SIZE || mRect[i].height < MIN_TU_SIZE) && mRect[i].width!=0) { const UInt numPels=mRect[i].width * mRect[i].height; if (numPels < (MIN_TU_SIZE*MIN_TU_SIZE)) { // this level doesn't have enough pixels to have 4 blocks of any relative dimension mRect[i].width = parent.mRect[i].width; mRect[i].height= parent.mRect[i].height; mCodeAll[i]=false; // go up a level, so only process one entry of a quadrant mTrDepthRelCU[i]--; } else if (mRect[i].width < mRect[i].height) { mRect[i].width=MIN_TU_SIZE; mRect[i].height=numPels/MIN_TU_SIZE; mCodeAll[i]=true; } else { mRect[i].height=MIN_TU_SIZE; mRect[i].width=numPels/MIN_TU_SIZE; mCodeAll[i]=true; } } else { mCodeAll[i]=true; } mOrigWidth[i]=mRect[i].width; if (!mCodeAll[i] && mbProcessLastOfLevel) { mRect[i].width=0; } } } Bool TComTURecurse::nextSection(const TComTU &parent) { if (mSplitMode==DONT_SPLIT) { mSection++; return false; } else { for(UInt i=0; i= parentRect.x0+parentRect.width) { mRect[i].x0=parentRect.x0; mRect[i].y0+=mRect[i].height; } if (!mCodeAll[i]) { if (!mbProcessLastOfLevel || mSection!=2) { mRect[i].width=0; } } } assert(mRect[COMPONENT_Cb].x0==mRect[COMPONENT_Cr].x0); assert(mRect[COMPONENT_Cb].y0==mRect[COMPONENT_Cr].y0); assert(mRect[COMPONENT_Cb].width==mRect[COMPONENT_Cr].width); assert(mRect[COMPONENT_Cb].height==mRect[COMPONENT_Cr].height); mAbsPartIdxTURelCU+=mAbsPartIdxStep; mSection++; return mSection< (1<isIntra(absPartIdx); } Bool TComTU::isNonTransformedResidualRotated(const ComponentID compID) { // rotation only for 4x4 intra, and is only used for non-transformed blocks (the latter is not checked here) return getCU()->getSlice()->getSPS()->getSpsRangeExtension().getTransformSkipRotationEnabledFlag() && mRect[compID].width == 4 && getCU()->isIntra(GetAbsPartIdxTU()); } UInt TComTU::getGolombRiceStatisticsIndex(const ComponentID compID) { TComDataCU *const pcCU = getCU(); const UInt absPartIdx = GetAbsPartIdxTU(compID); const Bool transformSkip = pcCU->getTransformSkip(absPartIdx, compID); const Bool transquantBypass = pcCU->getCUTransquantBypass(absPartIdx); //-------- const UInt channelTypeOffset = isChroma(compID) ? 2 : 0; const UInt nonTransformedOffset = (transformSkip || transquantBypass) ? 1 : 0; //-------- const UInt selectedIndex = channelTypeOffset + nonTransformedOffset; assert(selectedIndex < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS); return selectedIndex; } HM-HM-18.0/source/Lib/TLibCommon/TComTU.h000066400000000000000000000210701442026013100175360ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __TCOMTU__ #define __TCOMTU__ class TComTU; // forward declaration #include "CommonDef.h" #include "TComRectangle.h" #include "TComChromaFormat.h" class TComDataCU; // forward declaration //---------------------------------------------------------------------------------------------------------------------- class TComTU { public: typedef enum TU_SPLIT_MODE { DONT_SPLIT=0, VERTICAL_SPLIT=1, QUAD_SPLIT=2, NUMBER_OF_SPLIT_MODES=3 } SPLIT_MODE; static const UInt NUMBER_OF_SECTIONS[NUMBER_OF_SPLIT_MODES]; protected: ChromaFormat mChromaFormat; Bool mbProcessLastOfLevel; // if true, then if size n/2 x n/2 is invalid, the nxn block for a channel is processed only for the last block, not the first. UInt mCuDepth; UInt mTrDepthRelCU[MAX_NUM_COMPONENT]; UInt mSection; TU_SPLIT_MODE mSplitMode; TComRectangle mRect[MAX_NUM_COMPONENT]; Bool mCodeAll[MAX_NUM_COMPONENT]; UInt mOrigWidth[MAX_NUM_COMPONENT]; UInt mOffsets[MAX_NUM_COMPONENT]; UInt mAbsPartIdxCU; UInt mAbsPartIdxTURelCU; UInt mAbsPartIdxStep; TComDataCU *mpcCU; UInt mLog2TrLumaSize; TComTU *mpParent; TComTU(const TComTU &); // not defined - do not use TComTU&operator=(const TComTU &); // not defined - do not use public: TComTU( TComDataCU *pcCU, const UInt absPartIdxCU, const UInt cuDepth, const UInt initTrDepthRelCU); protected: TComTU( TComTU &parentLevel, const Bool bProcessLastOfLevel, const TU_SPLIT_MODE splitMode = QUAD_SPLIT, const Bool splitAtCurrentDepth = false, const ComponentID absPartIdxSourceComponent = COMPONENT_Y ); public: TComTU *Parent() { return mpParent; } const TComTU *Parent() const { return mpParent; } UInt getCoefficientOffset(const ComponentID compID) const { return mOffsets[compID]; } const TComRectangle &getRect(const ComponentID compID) const { return mRect[compID]; } Bool ProcessingAllQuadrants(const ComponentID compID) const { return mCodeAll[compID]; } Bool ProcessComponentSection(const ComponentID compID) const { return mRect[compID].width != 0; } Bool ProcessChannelSection(const ChannelType chType) const { return mRect[chType].width != 0; } UInt GetSectionNumber() const { return mSection; } UInt getCUDepth() const { return mCuDepth; } UInt GetTransformDepthTotal() const { return mCuDepth+GetTransformDepthRel(); } UInt GetTransformDepthTotalAdj(const ComponentID compID) const { return mCuDepth+GetTransformDepthRelAdj(compID); } UInt GetTransformDepthRel() const { return mTrDepthRelCU[COMPONENT_Y]; } UInt GetTransformDepthRelAdj(const ComponentID compID) const { return mTrDepthRelCU[compID]; } UInt GetTransformDepthRelAdj(const ChannelType chType) const { assert(isLuma(chType) || (mTrDepthRelCU[COMPONENT_Cb] == mTrDepthRelCU[COMPONENT_Cr])); return mTrDepthRelCU[isLuma(chType) ? COMPONENT_Y : COMPONENT_Cb]; } UInt GetAbsPartIdxCU() const { return mAbsPartIdxCU; } UInt GetRelPartIdxTU() const { return mAbsPartIdxTURelCU; } UInt GetRelPartIdxTU(const ComponentID compID) const { return ProcessingAllQuadrants(compID) ? mAbsPartIdxTURelCU : (mAbsPartIdxTURelCU & (~0x3)); } UInt GetAbsPartIdxTU() const { return GetAbsPartIdxCU() + GetRelPartIdxTU(); } UInt GetAbsPartIdxTU(const ComponentID compID) const { return GetAbsPartIdxCU() + GetRelPartIdxTU(compID); } UInt GetAbsPartIdxNumParts() const { return mAbsPartIdxStep; } UInt GetAbsPartIdxNumParts(const ComponentID compID) const { return ProcessingAllQuadrants(compID) ? mAbsPartIdxStep : (mAbsPartIdxStep * NUMBER_OF_SECTIONS[mSplitMode]); } ChromaFormat GetChromaFormat() const { return mChromaFormat; } TComDataCU *getCU() { return mpcCU; } const TComDataCU *getCU() const { return mpcCU; } Bool IsLastSection() const { return mSection+1>=((1<getDepth(idx) TComTURecurse( TComTU &parentLevel, //Parent TU from which recursion children are derived const Bool bProcessLastOfLevel, //If true (and the split results in a "step-up" for chroma), the chroma TU is colocated with the last luma TU instead of the first const TU_SPLIT_MODE splitMode = QUAD_SPLIT, //DONT_SPLIT = create one new TU as a copy of its parent, VERTICAL_SPLIT = split the TU into top and bottom halves, QUAD_SPLIT = split the TU into four equal quadrants const Bool splitAtCurrentDepth = false, //Set true to keep the current depth when applying a vertical or quad split const ComponentID absPartIdxSourceComponent = COMPONENT_Y //Specifies which component of the parent TU should be used to initialise the absPartIdx of the first child and the absPartIdx step (this is needed when splitting a "stepped-up" chroma TU) ) : TComTU(parentLevel, bProcessLastOfLevel, splitMode, splitAtCurrentDepth, absPartIdxSourceComponent) { } Bool nextSection(const TComTU &parent); // returns true if there is another section to process, and prepares internal structures, else returns false }; //---------------------------------------------------------------------------------------------------------------------- #endif HM-HM-18.0/source/Lib/TLibCommon/TComTrQuant.cpp000066400000000000000000004044241442026013100211470ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComTrQuant.cpp \brief transform and quantization class */ #include #include #include #include #include "TComTrQuant.h" #include "TComPic.h" #include "ContextTables.h" #include "TComTU.h" #include "Debug.h" typedef struct { Int iNNZbeforePos0; Double d64CodedLevelandDist; // distortion and level cost only Double d64UncodedDist; // all zero coded block distortion Double d64SigCost; Double d64SigCost_0; } coeffGroupRDStats; //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constants // ==================================================================================================================== #define RDOQ_CHROMA 1 ///< use of RDOQ in chroma // ==================================================================================================================== // QpParam constructor // ==================================================================================================================== QpParam::QpParam(const Int qpy, const ChannelType chType, const Int qpBdOffset, const Int chromaQPOffset, const ChromaFormat chFmt ) { Int baseQp; if(isLuma(chType)) { baseQp = qpy + qpBdOffset; } else { baseQp = Clip3( -qpBdOffset, (chromaQPMappingTableSize - 1), qpy + chromaQPOffset ); if(baseQp < 0) { baseQp = baseQp + qpBdOffset; } else { baseQp = getScaledChromaQP(baseQp, chFmt) + qpBdOffset; } } Qp =baseQp; per=baseQp/6; rem=baseQp%6; } QpParam::QpParam(const TComDataCU &cu, const ComponentID compID) { Int chromaQpOffset = 0; if (isChroma(compID)) { chromaQpOffset += cu.getSlice()->getPPS()->getQpOffset(compID); chromaQpOffset += cu.getSlice()->getSliceChromaQpDelta(compID); chromaQpOffset += cu.getSlice()->getPPS()->getPpsRangeExtension().getChromaQpOffsetListEntry(cu.getChromaQpAdj(0)).u.offset[Int(compID)-1]; } *this = QpParam(cu.getQP( 0 ), toChannelType(compID), cu.getSlice()->getSPS()->getQpBDOffset(toChannelType(compID)), chromaQpOffset, cu.getPic()->getChromaFormat()); } // ==================================================================================================================== // TComTrQuant class member functions // ==================================================================================================================== TComTrQuant::TComTrQuant() { // allocate temporary buffers m_plTempCoeff = new TCoeff[ MAX_CU_SIZE*MAX_CU_SIZE ]; // allocate bit estimation class (for RDOQ) m_pcEstBitsSbac = new estBitsSbacStruct; initScalingList(); } TComTrQuant::~TComTrQuant() { // delete temporary buffers if ( m_plTempCoeff ) { delete [] m_plTempCoeff; m_plTempCoeff = NULL; } // delete bit estimation class if ( m_pcEstBitsSbac ) { delete m_pcEstBitsSbac; } destroyScalingList(); } #if ADAPTIVE_QP_SELECTION Void TComTrQuant::storeSliceQpNext(TComSlice* pcSlice) { // NOTE: does this work with negative QPs or when some blocks are transquant-bypass enabled? Int qpBase = pcSlice->getSliceQpBase(); Int sliceQpused = pcSlice->getSliceQp(); Int sliceQpnext; Double alpha = qpBase < 17 ? 0.5 : 1; Int cnt=0; for(Int u=1; u<=LEVEL_RANGE; u++) { cnt += m_sliceNsamples[u] ; } if( !m_useRDOQ ) { sliceQpused = qpBase; alpha = 0.5; } if( cnt > 120 ) { Double sum = 0; Int k = 0; for(Int u=1; u0) ? (1<<(shift_1st-1)) : 0; const Int add_2nd = 1<<(shift_2nd-1); /* Horizontal transform */ for (i=0; i>shift_1st; } } /* Vertical transform */ for (i=0; i>shift_2nd; } } } /** NxN inverse transform (2D) using brute force matrix multiplication (3 nested loops) * \param coeff pointer to input data (transform coefficients) * \param block pointer to output data (residual) * \param uiStride stride of output data * \param uiTrSize transform size (uiTrSize x uiTrSize) * \param uiMode is Intra Prediction mode used in Mode-Dependent DCT/DST only */ Void xITr(Int bitDepth, TCoeff *coeff, Pel *block, UInt uiStride, UInt uiTrSize, Bool useDST, const Int maxLog2TrDynamicRange) { UInt i,j,k; TCoeff iSum; TCoeff tmp[MAX_TU_SIZE * MAX_TU_SIZE]; const TMatrixCoeff *iT; if (uiTrSize==4) { iT = (useDST ? g_as_DST_MAT_4[TRANSFORM_INVERSE][0] : g_aiT4[TRANSFORM_INVERSE][0]); } else if (uiTrSize==8) { iT = g_aiT8[TRANSFORM_INVERSE][0]; } else if (uiTrSize==16) { iT = g_aiT16[TRANSFORM_INVERSE][0]; } else if (uiTrSize==32) { iT = g_aiT32[TRANSFORM_INVERSE][0]; } else { assert(0); } const Int TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE]; const Int shift_1st = TRANSFORM_MATRIX_SHIFT + 1; //1 has been added to shift_1st at the expense of shift_2nd const Int shift_2nd = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth; const TCoeff clipMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff clipMaximum = (1 << maxLog2TrDynamicRange) - 1; assert(shift_2nd>=0); const Int add_1st = 1<<(shift_1st-1); const Int add_2nd = (shift_2nd>0) ? (1<<(shift_2nd-1)) : 0; /* Horizontal transform */ for (i=0; i(clipMinimum, clipMaximum, (iSum + add_1st)>>shift_1st); } } /* Vertical transform */ for (i=0; i(std::numeric_limits::min(), std::numeric_limits::max(), (iSum + add_2nd)>>shift_2nd); } } } #endif //MATRIX_MULT /** 4x4 forward transform implemented using partial butterfly structure (1D) * \param src input data (residual) * \param dst output data (transform coefficients) * \param shift specifies right shift after 1D transform * \param line */ Void partialButterfly4(TCoeff *src, TCoeff *dst, Int shift, Int line) { Int j; TCoeff E[2],O[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift; dst[2*line] = (g_aiT4[TRANSFORM_FORWARD][2][0]*E[0] + g_aiT4[TRANSFORM_FORWARD][2][1]*E[1] + add)>>shift; dst[line] = (g_aiT4[TRANSFORM_FORWARD][1][0]*O[0] + g_aiT4[TRANSFORM_FORWARD][1][1]*O[1] + add)>>shift; dst[3*line] = (g_aiT4[TRANSFORM_FORWARD][3][0]*O[0] + g_aiT4[TRANSFORM_FORWARD][3][1]*O[1] + add)>>shift; src += 4; dst ++; } } // Fast DST Algorithm. Full matrix multiplication for DST and Fast DST algorithm // give identical results Void fastForwardDst(TCoeff *block, TCoeff *coeff, Int shift) // input block, output coeff { Int i; TCoeff c[4]; TCoeff rnd_factor = (shift > 0) ? (1<<(shift-1)) : 0; for (i=0; i<4; i++) { // Intermediate Variables c[0] = block[4*i+0]; c[1] = block[4*i+1]; c[2] = block[4*i+2]; c[3] = block[4*i+3]; for (Int row = 0; row < 4; row++) { TCoeff result = 0; for (Int column = 0; column < 4; column++) { result += c[column] * g_as_DST_MAT_4[TRANSFORM_FORWARD][row][column]; // use the defined matrix, rather than hard-wired numbers } coeff[(row * 4) + i] = rightShift((result + rnd_factor), shift); } } } Void fastInverseDst(TCoeff *tmp, TCoeff *block, Int shift, const TCoeff outputMinimum, const TCoeff outputMaximum) // input tmp, output block { Int i; TCoeff c[4]; TCoeff rnd_factor = (shift > 0) ? (1<<(shift-1)) : 0; for (i=0; i<4; i++) { // Intermediate Variables c[0] = tmp[ i]; c[1] = tmp[4 +i]; c[2] = tmp[8 +i]; c[3] = tmp[12+i]; for (Int column = 0; column < 4; column++) { TCoeff &result = block[(i * 4) + column]; result = 0; for (Int row = 0; row < 4; row++) { result += c[row] * g_as_DST_MAT_4[TRANSFORM_INVERSE][row][column]; // use the defined matrix, rather than hard-wired numbers } result = Clip3( outputMinimum, outputMaximum, rightShift((result + rnd_factor), shift)); } } } /** 4x4 inverse transform implemented using partial butterfly structure (1D) * \param src input data (transform coefficients) * \param dst output data (residual) * \param shift specifies right shift after 1D transform * \param line * \param outputMinimum minimum for clipping * \param outputMaximum maximum for clipping */ Void partialButterflyInverse4(TCoeff *src, TCoeff *dst, Int shift, Int line, const TCoeff outputMinimum, const TCoeff outputMaximum) { Int j; TCoeff E[2],O[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift ); dst[1] = Clip3( outputMinimum, outputMaximum, (E[1] + O[1] + add)>>shift ); dst[2] = Clip3( outputMinimum, outputMaximum, (E[1] - O[1] + add)>>shift ); dst[3] = Clip3( outputMinimum, outputMaximum, (E[0] - O[0] + add)>>shift ); src ++; dst += 4; } } /** 8x8 forward transform implemented using partial butterfly structure (1D) * \param src input data (residual) * \param dst output data (transform coefficients) * \param shift specifies right shift after 1D transform * \param line */ Void partialButterfly8(TCoeff *src, TCoeff *dst, Int shift, Int line) { Int j,k; TCoeff E[4],O[4]; TCoeff EE[2],EO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift; dst[4*line] = (g_aiT8[TRANSFORM_FORWARD][4][0]*EE[0] + g_aiT8[TRANSFORM_FORWARD][4][1]*EE[1] + add)>>shift; dst[2*line] = (g_aiT8[TRANSFORM_FORWARD][2][0]*EO[0] + g_aiT8[TRANSFORM_FORWARD][2][1]*EO[1] + add)>>shift; dst[6*line] = (g_aiT8[TRANSFORM_FORWARD][6][0]*EO[0] + g_aiT8[TRANSFORM_FORWARD][6][1]*EO[1] + add)>>shift; dst[line] = (g_aiT8[TRANSFORM_FORWARD][1][0]*O[0] + g_aiT8[TRANSFORM_FORWARD][1][1]*O[1] + g_aiT8[TRANSFORM_FORWARD][1][2]*O[2] + g_aiT8[TRANSFORM_FORWARD][1][3]*O[3] + add)>>shift; dst[3*line] = (g_aiT8[TRANSFORM_FORWARD][3][0]*O[0] + g_aiT8[TRANSFORM_FORWARD][3][1]*O[1] + g_aiT8[TRANSFORM_FORWARD][3][2]*O[2] + g_aiT8[TRANSFORM_FORWARD][3][3]*O[3] + add)>>shift; dst[5*line] = (g_aiT8[TRANSFORM_FORWARD][5][0]*O[0] + g_aiT8[TRANSFORM_FORWARD][5][1]*O[1] + g_aiT8[TRANSFORM_FORWARD][5][2]*O[2] + g_aiT8[TRANSFORM_FORWARD][5][3]*O[3] + add)>>shift; dst[7*line] = (g_aiT8[TRANSFORM_FORWARD][7][0]*O[0] + g_aiT8[TRANSFORM_FORWARD][7][1]*O[1] + g_aiT8[TRANSFORM_FORWARD][7][2]*O[2] + g_aiT8[TRANSFORM_FORWARD][7][3]*O[3] + add)>>shift; src += 8; dst ++; } } /** 8x8 inverse transform implemented using partial butterfly structure (1D) * \param src input data (transform coefficients) * \param dst output data (residual) * \param shift specifies right shift after 1D transform * \param line * \param outputMinimum minimum for clipping * \param outputMaximum maximum for clipping */ Void partialButterflyInverse8(TCoeff *src, TCoeff *dst, Int shift, Int line, const TCoeff outputMinimum, const TCoeff outputMaximum) { Int j,k; TCoeff E[4],O[4]; TCoeff EE[2],EO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift ); dst[ k+4 ] = Clip3( outputMinimum, outputMaximum, (E[3-k] - O[3-k] + add)>>shift ); } src ++; dst += 8; } } /** 16x16 forward transform implemented using partial butterfly structure (1D) * \param src input data (residual) * \param dst output data (transform coefficients) * \param shift specifies right shift after 1D transform * \param line */ Void partialButterfly16(TCoeff *src, TCoeff *dst, Int shift, Int line) { Int j,k; TCoeff E[8],O[8]; TCoeff EE[4],EO[4]; TCoeff EEE[2],EEO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift; dst[ 8*line ] = (g_aiT16[TRANSFORM_FORWARD][ 8][0]*EEE[0] + g_aiT16[TRANSFORM_FORWARD][ 8][1]*EEE[1] + add)>>shift; dst[ 4*line ] = (g_aiT16[TRANSFORM_FORWARD][ 4][0]*EEO[0] + g_aiT16[TRANSFORM_FORWARD][ 4][1]*EEO[1] + add)>>shift; dst[ 12*line] = (g_aiT16[TRANSFORM_FORWARD][12][0]*EEO[0] + g_aiT16[TRANSFORM_FORWARD][12][1]*EEO[1] + add)>>shift; for (k=2;k<16;k+=4) { dst[ k*line ] = (g_aiT16[TRANSFORM_FORWARD][k][0]*EO[0] + g_aiT16[TRANSFORM_FORWARD][k][1]*EO[1] + g_aiT16[TRANSFORM_FORWARD][k][2]*EO[2] + g_aiT16[TRANSFORM_FORWARD][k][3]*EO[3] + add)>>shift; } for (k=1;k<16;k+=2) { dst[ k*line ] = (g_aiT16[TRANSFORM_FORWARD][k][0]*O[0] + g_aiT16[TRANSFORM_FORWARD][k][1]*O[1] + g_aiT16[TRANSFORM_FORWARD][k][2]*O[2] + g_aiT16[TRANSFORM_FORWARD][k][3]*O[3] + g_aiT16[TRANSFORM_FORWARD][k][4]*O[4] + g_aiT16[TRANSFORM_FORWARD][k][5]*O[5] + g_aiT16[TRANSFORM_FORWARD][k][6]*O[6] + g_aiT16[TRANSFORM_FORWARD][k][7]*O[7] + add)>>shift; } src += 16; dst ++; } } /** 16x16 inverse transform implemented using partial butterfly structure (1D) * \param src input data (transform coefficients) * \param dst output data (residual) * \param shift specifies right shift after 1D transform * \param line * \param outputMinimum minimum for clipping * \param outputMaximum maximum for clipping */ Void partialButterflyInverse16(TCoeff *src, TCoeff *dst, Int shift, Int line, const TCoeff outputMinimum, const TCoeff outputMaximum) { Int j,k; TCoeff E[8],O[8]; TCoeff EE[4],EO[4]; TCoeff EEE[2],EEO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift ); dst[k+8] = Clip3( outputMinimum, outputMaximum, (E[7-k] - O[7-k] + add)>>shift ); } src ++; dst += 16; } } /** 32x32 forward transform implemented using partial butterfly structure (1D) * \param src input data (residual) * \param dst output data (transform coefficients) * \param shift specifies right shift after 1D transform * \param line */ Void partialButterfly32(TCoeff *src, TCoeff *dst, Int shift, Int line) { Int j,k; TCoeff E[16],O[16]; TCoeff EE[8],EO[8]; TCoeff EEE[4],EEO[4]; TCoeff EEEE[2],EEEO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift; dst[ 16*line ] = (g_aiT32[TRANSFORM_FORWARD][16][0]*EEEE[0] + g_aiT32[TRANSFORM_FORWARD][16][1]*EEEE[1] + add)>>shift; dst[ 8*line ] = (g_aiT32[TRANSFORM_FORWARD][ 8][0]*EEEO[0] + g_aiT32[TRANSFORM_FORWARD][ 8][1]*EEEO[1] + add)>>shift; dst[ 24*line ] = (g_aiT32[TRANSFORM_FORWARD][24][0]*EEEO[0] + g_aiT32[TRANSFORM_FORWARD][24][1]*EEEO[1] + add)>>shift; for (k=4;k<32;k+=8) { dst[ k*line ] = (g_aiT32[TRANSFORM_FORWARD][k][0]*EEO[0] + g_aiT32[TRANSFORM_FORWARD][k][1]*EEO[1] + g_aiT32[TRANSFORM_FORWARD][k][2]*EEO[2] + g_aiT32[TRANSFORM_FORWARD][k][3]*EEO[3] + add)>>shift; } for (k=2;k<32;k+=4) { dst[ k*line ] = (g_aiT32[TRANSFORM_FORWARD][k][0]*EO[0] + g_aiT32[TRANSFORM_FORWARD][k][1]*EO[1] + g_aiT32[TRANSFORM_FORWARD][k][2]*EO[2] + g_aiT32[TRANSFORM_FORWARD][k][3]*EO[3] + g_aiT32[TRANSFORM_FORWARD][k][4]*EO[4] + g_aiT32[TRANSFORM_FORWARD][k][5]*EO[5] + g_aiT32[TRANSFORM_FORWARD][k][6]*EO[6] + g_aiT32[TRANSFORM_FORWARD][k][7]*EO[7] + add)>>shift; } for (k=1;k<32;k+=2) { dst[ k*line ] = (g_aiT32[TRANSFORM_FORWARD][k][ 0]*O[ 0] + g_aiT32[TRANSFORM_FORWARD][k][ 1]*O[ 1] + g_aiT32[TRANSFORM_FORWARD][k][ 2]*O[ 2] + g_aiT32[TRANSFORM_FORWARD][k][ 3]*O[ 3] + g_aiT32[TRANSFORM_FORWARD][k][ 4]*O[ 4] + g_aiT32[TRANSFORM_FORWARD][k][ 5]*O[ 5] + g_aiT32[TRANSFORM_FORWARD][k][ 6]*O[ 6] + g_aiT32[TRANSFORM_FORWARD][k][ 7]*O[ 7] + g_aiT32[TRANSFORM_FORWARD][k][ 8]*O[ 8] + g_aiT32[TRANSFORM_FORWARD][k][ 9]*O[ 9] + g_aiT32[TRANSFORM_FORWARD][k][10]*O[10] + g_aiT32[TRANSFORM_FORWARD][k][11]*O[11] + g_aiT32[TRANSFORM_FORWARD][k][12]*O[12] + g_aiT32[TRANSFORM_FORWARD][k][13]*O[13] + g_aiT32[TRANSFORM_FORWARD][k][14]*O[14] + g_aiT32[TRANSFORM_FORWARD][k][15]*O[15] + add)>>shift; } src += 32; dst ++; } } /** 32x32 inverse transform implemented using partial butterfly structure (1D) * \param src input data (transform coefficients) * \param dst output data (residual) * \param shift specifies right shift after 1D transform * \param line * \param outputMinimum minimum for clipping * \param outputMaximum maximum for clipping */ Void partialButterflyInverse32(TCoeff *src, TCoeff *dst, Int shift, Int line, const TCoeff outputMinimum, const TCoeff outputMaximum) { Int j,k; TCoeff E[16],O[16]; TCoeff EE[8],EO[8]; TCoeff EEE[4],EEO[4]; TCoeff EEEE[2],EEEO[2]; TCoeff add = (shift > 0) ? (1<<(shift-1)) : 0; for (j=0; j>shift ); dst[k+16] = Clip3( outputMinimum, outputMaximum, (E[15-k] - O[15-k] + add)>>shift ); } src ++; dst += 32; } } /** MxN forward transform (2D) * \param bitDepth [in] bit depth * \param block [in] residual block * \param coeff [out] transform coefficients * \param iWidth [in] width of transform * \param iHeight [in] height of transform * \param useDST [in] * \param maxLog2TrDynamicRange [in] */ Void xTrMxN(Int bitDepth, TCoeff *block, TCoeff *coeff, Int iWidth, Int iHeight, Bool useDST, const Int maxLog2TrDynamicRange) { const Int TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_FORWARD]; const Int shift_1st = ((g_aucConvertToBit[iWidth] + 2) + bitDepth + TRANSFORM_MATRIX_SHIFT) - maxLog2TrDynamicRange; const Int shift_2nd = (g_aucConvertToBit[iHeight] + 2) + TRANSFORM_MATRIX_SHIFT; assert(shift_1st >= 0); assert(shift_2nd >= 0); TCoeff tmp[ MAX_TU_SIZE * MAX_TU_SIZE ]; switch (iWidth) { case 4: { if ((iHeight == 4) && useDST) // Check for DCT or DST { fastForwardDst( block, tmp, shift_1st ); } else { partialButterfly4 ( block, tmp, shift_1st, iHeight ); } } break; case 8: partialButterfly8 ( block, tmp, shift_1st, iHeight ); break; case 16: partialButterfly16( block, tmp, shift_1st, iHeight ); break; case 32: partialButterfly32( block, tmp, shift_1st, iHeight ); break; default: assert(0); exit (1); break; } switch (iHeight) { case 4: { if ((iWidth == 4) && useDST) // Check for DCT or DST { fastForwardDst( tmp, coeff, shift_2nd ); } else { partialButterfly4 ( tmp, coeff, shift_2nd, iWidth ); } } break; case 8: partialButterfly8 ( tmp, coeff, shift_2nd, iWidth ); break; case 16: partialButterfly16( tmp, coeff, shift_2nd, iWidth ); break; case 32: partialButterfly32( tmp, coeff, shift_2nd, iWidth ); break; default: assert(0); exit (1); break; } } /** MxN inverse transform (2D) * \param bitDepth [in] bit depth * \param coeff [in] transform coefficients * \param block [out] residual block * \param iWidth [in] width of transform * \param iHeight [in] height of transform * \param useDST [in] * \param maxLog2TrDynamicRange [in] */ Void xITrMxN(Int bitDepth, TCoeff *coeff, TCoeff *block, Int iWidth, Int iHeight, Bool useDST, const Int maxLog2TrDynamicRange) { const Int TRANSFORM_MATRIX_SHIFT = g_transformMatrixShift[TRANSFORM_INVERSE]; Int shift_1st = TRANSFORM_MATRIX_SHIFT + 1; //1 has been added to shift_1st at the expense of shift_2nd Int shift_2nd = (TRANSFORM_MATRIX_SHIFT + maxLog2TrDynamicRange - 1) - bitDepth; const TCoeff clipMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff clipMaximum = (1 << maxLog2TrDynamicRange) - 1; assert(shift_1st >= 0); assert(shift_2nd >= 0); TCoeff tmp[MAX_TU_SIZE * MAX_TU_SIZE]; switch (iHeight) { case 4: { if ((iWidth == 4) && useDST) // Check for DCT or DST { fastInverseDst( coeff, tmp, shift_1st, clipMinimum, clipMaximum); } else { partialButterflyInverse4 ( coeff, tmp, shift_1st, iWidth, clipMinimum, clipMaximum); } } break; case 8: partialButterflyInverse8 ( coeff, tmp, shift_1st, iWidth, clipMinimum, clipMaximum); break; case 16: partialButterflyInverse16( coeff, tmp, shift_1st, iWidth, clipMinimum, clipMaximum); break; case 32: partialButterflyInverse32( coeff, tmp, shift_1st, iWidth, clipMinimum, clipMaximum); break; default: assert(0); exit (1); break; } switch (iWidth) { // Clipping here is not in the standard, but is used to protect the "Pel" data type into which the inverse-transformed samples will be copied case 4: { if ((iHeight == 4) && useDST) // Check for DCT or DST { fastInverseDst( tmp, block, shift_2nd, std::numeric_limits::min(), std::numeric_limits::max() ); } else { partialButterflyInverse4 ( tmp, block, shift_2nd, iHeight, std::numeric_limits::min(), std::numeric_limits::max()); } } break; case 8: partialButterflyInverse8 ( tmp, block, shift_2nd, iHeight, std::numeric_limits::min(), std::numeric_limits::max()); break; case 16: partialButterflyInverse16( tmp, block, shift_2nd, iHeight, std::numeric_limits::min(), std::numeric_limits::max()); break; case 32: partialButterflyInverse32( tmp, block, shift_2nd, iHeight, std::numeric_limits::min(), std::numeric_limits::max()); break; default: assert(0); exit (1); break; } } // To minimize the distortion only. No rate is considered. Void TComTrQuant::signBitHidingHDQ( TCoeff* pQCoef, TCoeff* pCoef, TCoeff* deltaU, const TUEntropyCodingParameters &codingParameters, const Int maxLog2TrDynamicRange ) { const UInt width = codingParameters.widthInGroups << MLS_CG_LOG2_WIDTH; const UInt height = codingParameters.heightInGroups << MLS_CG_LOG2_HEIGHT; const UInt groupSize = 1 << MLS_CG_SIZE; const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; Int lastCG = -1; Int absSum = 0 ; Int n ; for( Int subSet = (width*height-1) >> MLS_CG_SIZE; subSet >= 0; subSet-- ) { Int subPos = subSet << MLS_CG_SIZE; Int firstNZPosInCG=groupSize , lastNZPosInCG=-1 ; absSum = 0 ; for(n = groupSize-1; n >= 0; --n ) { if( pQCoef[ codingParameters.scan[ n + subPos ]] ) { lastNZPosInCG = n; break; } } for(n = 0; n =0 && lastCG==-1) { lastCG = 1 ; } if( lastNZPosInCG-firstNZPosInCG>=SBH_THRESHOLD ) { UInt signbit = (pQCoef[codingParameters.scan[subPos+firstNZPosInCG]]>0?0:1) ; if( signbit!=(absSum&0x1) ) //compare signbit with sum_parity { TCoeff curCost = std::numeric_limits::max(); TCoeff minCostInc = std::numeric_limits::max(); Int minPos =-1, finalChange=0, curChange=0; for( n = (lastCG==1?lastNZPosInCG:groupSize-1) ; n >= 0; --n ) { UInt blkPos = codingParameters.scan[ n+subPos ]; if(pQCoef[ blkPos ] != 0 ) { if(deltaU[blkPos]>0) { curCost = - deltaU[blkPos]; curChange=1 ; } else { //curChange =-1; if(n==firstNZPosInCG && abs(pQCoef[blkPos])==1) { curCost = std::numeric_limits::max(); } else { curCost = deltaU[blkPos]; curChange =-1; } } } else { if(n=0?0:1); if(thisSignBit != signbit ) { curCost = std::numeric_limits::max(); } else { curCost = - (deltaU[blkPos]) ; curChange = 1 ; } } else { curCost = - (deltaU[blkPos]) ; curChange = 1 ; } } if( curCost=0) { pQCoef[minPos] += finalChange ; } else { pQCoef[minPos] -= finalChange ; } } // Hide } if(lastCG==1) { lastCG=0 ; } } // TU loop return; } Void TComTrQuant::xQuant( TComTU &rTu, TCoeff * pSrc, TCoeff * pDes, #if ADAPTIVE_QP_SELECTION TCoeff *pArlDes, #endif TCoeff &uiAbsSum, const ComponentID compID, const QpParam &cQP ) { const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; TComDataCU* pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); TCoeff* piCoef = pSrc; TCoeff* piQCoef = pDes; #if ADAPTIVE_QP_SELECTION TCoeff* piArlCCoef = pArlDes; #endif const Bool useTransformSkip = pcCU->getTransformSkip(uiAbsPartIdx, compID); const Int maxLog2TrDynamicRange = pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); Bool useRDOQ = useTransformSkip ? m_useRDOQTS : m_useRDOQ; if ( useRDOQ && (isLuma(compID) || RDOQ_CHROMA) ) { if ( !m_useSelectiveRDOQ || xNeedRDOQ( rTu, piCoef, compID, cQP ) ) { #if ADAPTIVE_QP_SELECTION xRateDistOptQuant( rTu, piCoef, pDes, pArlDes, uiAbsSum, compID, cQP ); #else xRateDistOptQuant( rTu, piCoef, pDes, uiAbsSum, compID, cQP ); #endif } else { memset( pDes, 0, sizeof( TCoeff ) * uiWidth *uiHeight ); uiAbsSum = 0; } } else { TUEntropyCodingParameters codingParameters; getTUEntropyCodingParameters(codingParameters, rTu, compID); const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; TCoeff deltaU[MAX_TU_SIZE * MAX_TU_SIZE]; const UInt uiLog2TrSize = rTu.GetEquivalentLog2TrSize(compID); Int scalingListType = getScalingListType(pcCU->getPredictionMode(uiAbsPartIdx), compID); assert(scalingListType < SCALING_LIST_NUM); Int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem, uiLog2TrSize-2); const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)); const Int defaultQuantisationCoefficient = g_quantScales[cQP.rem]; /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller) * Then a QP+3 (sqrt(2)) or QP-3 (1/sqrt(2)) method could be used to get the required result */ // Represents scaling through forward transform Int iTransformShift = getTransformShift(channelBitDepth, uiLog2TrSize, maxLog2TrDynamicRange); if (useTransformSkip && pcCU->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag()) { iTransformShift = std::max(0, iTransformShift); } const Int iQBits = QUANT_SHIFT + cQP.per + iTransformShift; // QBits will be OK for any internal bit depth as the reduction in transform shift is balanced by an increase in Qp_per due to QpBDOffset #if ADAPTIVE_QP_SELECTION Int iQBitsC = MAX_INT; Int iAddC = MAX_INT; if (m_bUseAdaptQpSelect) { iQBitsC = iQBits - ARL_C_PRECISION; iAddC = 1 << (iQBitsC-1); } #endif const Int iAdd = (pcCU->getSlice()->getSliceType()==I_SLICE ? 171 : 85) << (iQBits-9); const Int qBits8 = iQBits - 8; for( Int uiBlockPos = 0; uiBlockPos < uiWidth*uiHeight; uiBlockPos++ ) { const TCoeff iLevel = piCoef[uiBlockPos]; const TCoeff iSign = (iLevel < 0 ? -1: 1); const Int64 tmpLevel = (Int64)abs(iLevel) * (enableScalingLists ? piQuantCoeff[uiBlockPos] : defaultQuantisationCoefficient); #if ADAPTIVE_QP_SELECTION if( m_bUseAdaptQpSelect ) { piArlCCoef[uiBlockPos] = (TCoeff)((tmpLevel + iAddC ) >> iQBitsC); } #endif const TCoeff quantisedMagnitude = TCoeff((tmpLevel + iAdd ) >> iQBits); deltaU[uiBlockPos] = (TCoeff)((tmpLevel - (quantisedMagnitude<> qBits8); uiAbsSum += quantisedMagnitude; const TCoeff quantisedCoefficient = quantisedMagnitude * iSign; piQCoef[uiBlockPos] = Clip3( entropyCodingMinimum, entropyCodingMaximum, quantisedCoefficient ); } // for n if( pcCU->getSlice()->getPPS()->getSignDataHidingEnabledFlag() ) { if(uiAbsSum >= 2) //this prevents TUs with only one coefficient of value 1 from being tested { signBitHidingHDQ( piQCoef, piCoef, deltaU, codingParameters, maxLog2TrDynamicRange ) ; } } } //if RDOQ //return; } Bool TComTrQuant::xNeedRDOQ( TComTU &rTu, TCoeff * pSrc, const ComponentID compID, const QpParam &cQP ) { const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; TComDataCU* pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); TCoeff* piCoef = pSrc; const Bool useTransformSkip = pcCU->getTransformSkip(uiAbsPartIdx, compID); const Int maxLog2TrDynamicRange = pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); const UInt uiLog2TrSize = rTu.GetEquivalentLog2TrSize(compID); Int scalingListType = getScalingListType(pcCU->getPredictionMode(uiAbsPartIdx), compID); assert(scalingListType < SCALING_LIST_NUM); Int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem, uiLog2TrSize-2); const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)); const Int defaultQuantisationCoefficient = g_quantScales[cQP.rem]; /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller) * Then a QP+3 (sqrt(2)) or QP-3 (1/sqrt(2)) method could be used to get the required result */ // Represents scaling through forward transform Int iTransformShift = getTransformShift(channelBitDepth, uiLog2TrSize, maxLog2TrDynamicRange); if (useTransformSkip && pcCU->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag()) { iTransformShift = std::max(0, iTransformShift); } const Int iQBits = QUANT_SHIFT + cQP.per + iTransformShift; // QBits will be OK for any internal bit depth as the reduction in transform shift is balanced by an increase in Qp_per due to QpBDOffset // iAdd is different from the iAdd used in normal quantization const Int iAdd = (compID == COMPONENT_Y ? 171 : 256) << (iQBits-9); for( Int uiBlockPos = 0; uiBlockPos < uiWidth*uiHeight; uiBlockPos++ ) { const TCoeff iLevel = piCoef[uiBlockPos]; const Int64 tmpLevel = (Int64)abs(iLevel) * (enableScalingLists ? piQuantCoeff[uiBlockPos] : defaultQuantisationCoefficient); const TCoeff quantisedMagnitude = TCoeff((tmpLevel + iAdd ) >> iQBits); if ( quantisedMagnitude != 0 ) { return true; } } // for n return false; } Void TComTrQuant::xDeQuant( TComTU &rTu, const TCoeff * pSrc, TCoeff * pDes, const ComponentID compID, const QpParam &cQP ) { assert(compIDgetSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); const TCoeff transformMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff transformMaximum = (1 << maxLog2TrDynamicRange) - 1; const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)); const Int scalingListType = getScalingListType(pcCU->getPredictionMode(uiAbsPartIdx), compID); #if O0043_BEST_EFFORT_DECODING const Int channelBitDepth = pcCU->getSlice()->getSPS()->getStreamBitDepth(toChannelType(compID)); #else const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); #endif assert (scalingListType < SCALING_LIST_NUM); assert ( uiWidth <= m_uiMaxTrSize ); // Represents scaling through forward transform const Bool bClipTransformShiftTo0 = (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0) && pcCU->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag(); const Int originalTransformShift = getTransformShift(channelBitDepth, uiLog2TrSize, maxLog2TrDynamicRange); const Int iTransformShift = bClipTransformShiftTo0 ? std::max(0, originalTransformShift) : originalTransformShift; const Int QP_per = cQP.per; const Int QP_rem = cQP.rem; const Int rightShift = (IQUANT_SHIFT - (iTransformShift + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0); if(enableScalingLists) { //from the dequantisation equation: //iCoeffQ = ((Intermediate_Int(clipQCoef) * piDequantCoef[deQuantIdx]) + iAdd ) >> rightShift //(sizeof(Intermediate_Int) * 8) = inputBitDepth + dequantCoefBits - rightShift const UInt dequantCoefBits = 1 + IQUANT_SHIFT + SCALING_LIST_BITS; const UInt targetInputBitDepth = std::min((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - dequantCoefBits)); const Intermediate_Int inputMinimum = -(1 << (targetInputBitDepth - 1)); const Intermediate_Int inputMaximum = (1 << (targetInputBitDepth - 1)) - 1; Int *piDequantCoef = getDequantCoeff(scalingListType,QP_rem,uiLog2TrSize-2); if(rightShift > 0) { const Intermediate_Int iAdd = 1 << (rightShift - 1); for( Int n = 0; n < numSamplesInBlock; n++ ) { const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, piQCoef[n])); const Intermediate_Int iCoeffQ = ((Intermediate_Int(clipQCoef) * piDequantCoef[n]) + iAdd ) >> rightShift; piCoef[n] = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } else { const Int leftShift = -rightShift; for( Int n = 0; n < numSamplesInBlock; n++ ) { const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, piQCoef[n])); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * piDequantCoef[n]) << leftShift; piCoef[n] = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } } else { const Int scale = g_invQuantScales[QP_rem]; const Int scaleBits = (IQUANT_SHIFT + 1) ; //from the dequantisation equation: //iCoeffQ = Intermediate_Int((Int64(clipQCoef) * scale + iAdd) >> rightShift); //(sizeof(Intermediate_Int) * 8) = inputBitDepth + scaleBits - rightShift const UInt targetInputBitDepth = std::min((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - scaleBits)); const Intermediate_Int inputMinimum = -(1 << (targetInputBitDepth - 1)); const Intermediate_Int inputMaximum = (1 << (targetInputBitDepth - 1)) - 1; if (rightShift > 0) { const Intermediate_Int iAdd = 1 << (rightShift - 1); for( Int n = 0; n < numSamplesInBlock; n++ ) { const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, piQCoef[n])); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift; piCoef[n] = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } else { const Int leftShift = -rightShift; for( Int n = 0; n < numSamplesInBlock; n++ ) { const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, piQCoef[n])); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * scale) << leftShift; piCoef[n] = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } } } Void TComTrQuant::init( UInt uiMaxTrSize, Bool bUseRDOQ, Bool bUseRDOQTS, Bool useSelectiveRDOQ, Bool bEnc, Bool useTransformSkipFast #if ADAPTIVE_QP_SELECTION , Bool bUseAdaptQpSelect #endif ) { m_uiMaxTrSize = uiMaxTrSize; m_bEnc = bEnc; m_useRDOQ = bUseRDOQ; m_useRDOQTS = bUseRDOQTS; m_useSelectiveRDOQ = useSelectiveRDOQ; #if ADAPTIVE_QP_SELECTION m_bUseAdaptQpSelect = bUseAdaptQpSelect; #endif m_useTransformSkipFast = useTransformSkipFast; } Void TComTrQuant::transformNxN( TComTU & rTu, const ComponentID compID, Pel * pcResidual, const UInt uiStride, TCoeff * rpcCoeff, #if ADAPTIVE_QP_SELECTION TCoeff * pcArlCoeff, #endif TCoeff & uiAbsSum, const QpParam & cQP ) { const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; TComDataCU* pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiOrgTrDepth = rTu.GetTransformDepthRel(); uiAbsSum=0; RDPCMMode rdpcmMode = RDPCM_OFF; rdpcmNxN( rTu, compID, pcResidual, uiStride, cQP, rpcCoeff, uiAbsSum, rdpcmMode ); if (rdpcmMode == RDPCM_OFF) { uiAbsSum = 0; //transform and quantise if(pcCU->getCUTransquantBypass(uiAbsPartIdx)) { const Bool rotateResidual = rTu.isNonTransformedResidualRotated(compID); const UInt uiSizeMinus1 = (uiWidth * uiHeight) - 1; for (UInt y = 0, coefficientIndex = 0; ygetSlice()->getSPS()->getMaxTrSize() >= uiWidth) ); if(pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0) { xTransformSkip( pcResidual, uiStride, m_plTempCoeff, rTu, compID ); } else { const Int channelBitDepth=pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); xT( channelBitDepth, rTu.useDST(compID), pcResidual, uiStride, m_plTempCoeff, uiWidth, uiHeight, pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)) ); } #if DEBUG_TRANSFORM_AND_QUANTISE std::cout << g_debugCounter << ": " << uiWidth << "x" << uiHeight << " channel " << compID << " TU between transform and quantiser\n"; printBlock(m_plTempCoeff, uiWidth, uiHeight, uiWidth); #endif xQuant( rTu, m_plTempCoeff, rpcCoeff, #if ADAPTIVE_QP_SELECTION pcArlCoeff, #endif uiAbsSum, compID, cQP ); #if DEBUG_TRANSFORM_AND_QUANTISE std::cout << g_debugCounter << ": " << uiWidth << "x" << uiHeight << " channel " << compID << " TU at output of quantiser\n"; printBlock(rpcCoeff, uiWidth, uiHeight, uiWidth); #endif } } //set the CBF pcCU->setCbfPartRange((((uiAbsSum > 0) ? 1 : 0) << uiOrgTrDepth), compID, uiAbsPartIdx, rTu.GetAbsPartIdxNumParts(compID)); } Void TComTrQuant::invTransformNxN( TComTU &rTu, const ComponentID compID, Pel *pcResidual, const UInt uiStride, TCoeff * pcCoeff, const QpParam &cQP DEBUG_STRING_FN_DECLAREP(psDebug)) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; if (uiWidth != uiHeight) //for intra, the TU will have been split above this level, so this condition won't be true, hence this only affects inter { //------------------------------------------------ //recurse deeper TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID); do { //------------------ const UInt lineOffset = subTURecurse.GetSectionNumber() * subTURecurse.getRect(compID).height; Pel *subTUResidual = pcResidual + (lineOffset * uiStride); TCoeff *subTUCoefficients = pcCoeff + (lineOffset * subTURecurse.getRect(compID).width); invTransformNxN(subTURecurse, compID, subTUResidual, uiStride, subTUCoefficients, cQP DEBUG_STRING_PASS_INTO(psDebug)); //------------------ } while (subTURecurse.nextSection(rTu)); //------------------------------------------------ return; } #if DEBUG_STRING if (psDebug) { std::stringstream ss(stringstream::out); printBlockToStream(ss, (compID==0)?"###InvTran ip Ch0: " : ((compID==1)?"###InvTran ip Ch1: ":"###InvTran ip Ch2: "), pcCoeff, uiWidth, uiHeight, uiWidth); DEBUG_STRING_APPEND((*psDebug), ss.str()) } #endif if(pcCU->getCUTransquantBypass(uiAbsPartIdx)) { const Bool rotateResidual = rTu.isNonTransformedResidualRotated(compID); const UInt uiSizeMinus1 = (uiWidth * uiHeight) - 1; for (UInt y = 0, coefficientIndex = 0; ygetTransformSkip(uiAbsPartIdx, compID)) { xITransformSkip( m_plTempCoeff, pcResidual, uiStride, rTu, compID ); #if DEBUG_STRING if (psDebug) { std::stringstream ss(stringstream::out); printBlockToStream(ss, "###InvTran resi: ", pcResidual, uiWidth, uiHeight, uiStride); (*psDebug)+=ss.str(); (*psDebug)+="(<- was a Transform-skipped block)\n"; } #endif } else { #if O0043_BEST_EFFORT_DECODING const Int channelBitDepth = pcCU->getSlice()->getSPS()->getStreamBitDepth(toChannelType(compID)); #else const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); #endif xIT( channelBitDepth, rTu.useDST(compID), m_plTempCoeff, pcResidual, uiStride, uiWidth, uiHeight, pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)) ); #if DEBUG_STRING if (psDebug) { std::stringstream ss(stringstream::out); printBlockToStream(ss, "###InvTran resi: ", pcResidual, uiWidth, uiHeight, uiStride); (*psDebug)+=ss.str(); (*psDebug)+="(<- was a Transformed block)\n"; } #endif } #if DEBUG_TRANSFORM_AND_QUANTISE std::cout << g_debugCounter << ": " << uiWidth << "x" << uiHeight << " channel " << compID << " TU at output of inverse-transform\n"; printBlock(pcResidual, uiWidth, uiHeight, uiStride); g_debugCounter++; #endif } invRdpcmNxN( rTu, compID, pcResidual, uiStride ); } Void TComTrQuant::invRecurTransformNxN( const ComponentID compID, TComYuv *pResidual, TComTU &rTu) { if (!rTu.ProcessComponentSection(compID)) { return; } TComDataCU* pcCU = rTu.getCU(); UInt absPartIdxTU = rTu.GetAbsPartIdxTU(); UInt uiTrMode=rTu.GetTransformDepthRel(); if( (pcCU->getCbf(absPartIdxTU, compID, uiTrMode) == 0) && (isLuma(compID) || !pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) ) { return; } if( uiTrMode == pcCU->getTransformIdx( absPartIdxTU ) ) { const TComRectangle &tuRect = rTu.getRect(compID); const Int uiStride = pResidual->getStride( compID ); Pel *rpcResidual = pResidual->getAddr( compID ); UInt uiAddr = (tuRect.x0 + uiStride*tuRect.y0); Pel *pResi = rpcResidual + uiAddr; TCoeff *pcCoeff = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID); const QpParam cQP(*pcCU, compID); if(pcCU->getCbf(absPartIdxTU, compID, uiTrMode) != 0) { DEBUG_STRING_NEW(sTemp) #if DEBUG_STRING std::string *psDebug=((DebugOptionList::DebugString_InvTran.getInt()&(pcCU->isIntra(absPartIdxTU)?1:(pcCU->isInter(absPartIdxTU)?2:4)))!=0) ? &sTemp : 0; #endif invTransformNxN( rTu, compID, pResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) ); #if DEBUG_STRING if (psDebug != 0) { std::cout << (*psDebug); } #endif } if (isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(absPartIdxTU, compID) != 0)) { const Pel *piResiLuma = pResidual->getAddr( COMPONENT_Y ); const Int strideLuma = pResidual->getStride( COMPONENT_Y ); const Int tuWidth = rTu.getRect( compID ).width; const Int tuHeight = rTu.getRect( compID ).height; if(pcCU->getCbf(absPartIdxTU, COMPONENT_Y, uiTrMode) != 0) { pResi = rpcResidual + uiAddr; const Pel *pResiLuma = piResiLuma + uiAddr; crossComponentPrediction( rTu, compID, pResiLuma, pResi, pResi, tuWidth, tuHeight, strideLuma, uiStride, uiStride, true ); } } } else { TComTURecurse tuRecurseChild(rTu, false); do { invRecurTransformNxN( compID, pResidual, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } } Void TComTrQuant::applyForwardRDPCM( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride, const QpParam& cQP, TCoeff* pcCoeff, TCoeff &uiAbsSum, const RDPCMMode mode ) { TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const Bool bLossless = pcCU->getCUTransquantBypass( uiAbsPartIdx ); const UInt uiWidth = rTu.getRect(compID).width; const UInt uiHeight = rTu.getRect(compID).height; const Bool rotateResidual = rTu.isNonTransformedResidualRotated(compID); const UInt uiSizeMinus1 = (uiWidth * uiHeight) - 1; UInt uiX = 0; UInt uiY = 0; UInt &majorAxis = (mode == RDPCM_VER) ? uiX : uiY; UInt &minorAxis = (mode == RDPCM_VER) ? uiY : uiX; const UInt majorAxisLimit = (mode == RDPCM_VER) ? uiWidth : uiHeight; const UInt minorAxisLimit = (mode == RDPCM_VER) ? uiHeight : uiWidth; const Bool bUseHalfRoundingPoint = (mode != RDPCM_OFF); uiAbsSum = 0; for ( majorAxis = 0; majorAxis < majorAxisLimit; majorAxis++ ) { TCoeff accumulatorValue = 0; // 32-bit accumulator for ( minorAxis = 0; minorAxis < minorAxisLimit; minorAxis++ ) { const UInt sampleIndex = (uiY * uiWidth) + uiX; const UInt coefficientIndex = (rotateResidual ? (uiSizeMinus1-sampleIndex) : sampleIndex); const Pel currentSample = pcResidual[(uiY * uiStride) + uiX]; const TCoeff encoderSideDelta = TCoeff(currentSample) - accumulatorValue; Pel reconstructedDelta; if ( bLossless ) { pcCoeff[coefficientIndex] = encoderSideDelta; reconstructedDelta = (Pel) encoderSideDelta; } else { transformSkipQuantOneSample(rTu, compID, encoderSideDelta, pcCoeff, coefficientIndex, cQP, bUseHalfRoundingPoint); invTrSkipDeQuantOneSample (rTu, compID, pcCoeff[coefficientIndex], reconstructedDelta, cQP, coefficientIndex); } uiAbsSum += abs(pcCoeff[coefficientIndex]); if (mode != RDPCM_OFF) { accumulatorValue += reconstructedDelta; } } } } Void TComTrQuant::rdpcmNxN ( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride, const QpParam& cQP, TCoeff* pcCoeff, TCoeff &uiAbsSum, RDPCMMode& rdpcmMode ) { TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); if (!pcCU->isRDPCMEnabled(uiAbsPartIdx) || ((pcCU->getTransformSkip(uiAbsPartIdx, compID) == 0) && !pcCU->getCUTransquantBypass(uiAbsPartIdx))) { rdpcmMode = RDPCM_OFF; } else if ( pcCU->isIntra( uiAbsPartIdx ) ) { const ChromaFormat chFmt = pcCU->getPic()->getPicYuvOrg()->getChromaFormat(); const ChannelType chType = toChannelType(compID); const UInt uiChPredMode = pcCU->getIntraDir( chType, uiAbsPartIdx ); const TComSPS *sps=pcCU->getSlice()->getSPS(); const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())); const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && isChroma(compID)) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode; const UInt uiChFinalMode = ((chFmt == CHROMA_422) && isChroma(compID)) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; if (uiChFinalMode == VER_IDX || uiChFinalMode == HOR_IDX) { rdpcmMode = (uiChFinalMode == VER_IDX) ? RDPCM_VER : RDPCM_HOR; applyForwardRDPCM( rTu, compID, pcResidual, uiStride, cQP, pcCoeff, uiAbsSum, rdpcmMode ); } else { rdpcmMode = RDPCM_OFF; } } else // not intra, need to select the best mode { const UInt uiWidth = rTu.getRect(compID).width; const UInt uiHeight = rTu.getRect(compID).height; RDPCMMode bestMode = NUMBER_OF_RDPCM_MODES; TCoeff bestAbsSum = std::numeric_limits::max(); TCoeff bestCoefficients[MAX_TU_SIZE * MAX_TU_SIZE]; for (UInt modeIndex = 0; modeIndex < NUMBER_OF_RDPCM_MODES; modeIndex++) { const RDPCMMode mode = RDPCMMode(modeIndex); TCoeff currAbsSum = 0; applyForwardRDPCM( rTu, compID, pcResidual, uiStride, cQP, pcCoeff, currAbsSum, mode ); if (currAbsSum < bestAbsSum) { bestMode = mode; bestAbsSum = currAbsSum; if (mode != RDPCM_OFF) { memcpy(bestCoefficients, pcCoeff, (uiWidth * uiHeight * sizeof(TCoeff))); } } } rdpcmMode = bestMode; uiAbsSum = bestAbsSum; if (rdpcmMode != RDPCM_OFF) //the TU is re-transformed and quantised if DPCM_OFF is returned, so there is no need to preserve it here { memcpy(pcCoeff, bestCoefficients, (uiWidth * uiHeight * sizeof(TCoeff))); } } pcCU->setExplicitRdpcmModePartRange(rdpcmMode, compID, uiAbsPartIdx, rTu.GetAbsPartIdxNumParts(compID)); } Void TComTrQuant::invRdpcmNxN( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride ) { TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); if (pcCU->isRDPCMEnabled( uiAbsPartIdx ) && ((pcCU->getTransformSkip(uiAbsPartIdx, compID ) != 0) || pcCU->getCUTransquantBypass(uiAbsPartIdx))) { const UInt uiWidth = rTu.getRect(compID).width; const UInt uiHeight = rTu.getRect(compID).height; RDPCMMode rdpcmMode = RDPCM_OFF; if ( pcCU->isIntra( uiAbsPartIdx ) ) { const ChromaFormat chFmt = pcCU->getPic()->getPicYuvRec()->getChromaFormat(); const ChannelType chType = toChannelType(compID); const UInt uiChPredMode = pcCU->getIntraDir( chType, uiAbsPartIdx ); const TComSPS *sps=pcCU->getSlice()->getSPS(); const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize())); const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && isChroma(compID)) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode; const UInt uiChFinalMode = ((chFmt == CHROMA_422) && isChroma(compID)) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; if (uiChFinalMode == VER_IDX || uiChFinalMode == HOR_IDX) { rdpcmMode = (uiChFinalMode == VER_IDX) ? RDPCM_VER : RDPCM_HOR; } } else // not intra case { rdpcmMode = RDPCMMode(pcCU->getExplicitRdpcmMode( compID, uiAbsPartIdx )); } const TCoeff pelMin=(TCoeff) std::numeric_limits::min(); const TCoeff pelMax=(TCoeff) std::numeric_limits::max(); if (rdpcmMode == RDPCM_VER) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { Pel *pcCurResidual = pcResidual+uiX; TCoeff accumulator = *pcCurResidual; // 32-bit accumulator pcCurResidual+=uiStride; for( UInt uiY = 1; uiY < uiHeight; uiY++, pcCurResidual+=uiStride ) { accumulator += *(pcCurResidual); *pcCurResidual = (Pel)Clip3(pelMin, pelMax, accumulator); } } } else if (rdpcmMode == RDPCM_HOR) { for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { Pel *pcCurResidual = pcResidual+uiY*uiStride; TCoeff accumulator = *pcCurResidual; pcCurResidual++; for( UInt uiX = 1; uiX < uiWidth; uiX++, pcCurResidual++ ) { accumulator += *(pcCurResidual); *pcCurResidual = (Pel)Clip3(pelMin, pelMax, accumulator); } } } } } // ------------------------------------------------------------------------------------------------ // Logical transform // ------------------------------------------------------------------------------------------------ /** Wrapper function between HM interface and core NxN forward transform (2D) * \param channelBitDepth bit depth of channel * \param useDST * \param piBlkResi input data (residual) * \param uiStride stride of input residual data * \param psCoeff output data (transform coefficients) * \param iWidth transform width * \param iHeight transform height * \param maxLog2TrDynamicRange */ Void TComTrQuant::xT( const Int channelBitDepth, Bool useDST, Pel* piBlkResi, UInt uiStride, TCoeff* psCoeff, Int iWidth, Int iHeight, const Int maxLog2TrDynamicRange ) { #if MATRIX_MULT if( iWidth == iHeight) { xTr(channelBitDepth, piBlkResi, psCoeff, uiStride, (UInt)iWidth, useDST, maxLog2TrDynamicRange); return; } #endif TCoeff block[ MAX_TU_SIZE * MAX_TU_SIZE ]; TCoeff coeff[ MAX_TU_SIZE * MAX_TU_SIZE ]; for (Int y = 0; y < iHeight; y++) { for (Int x = 0; x < iWidth; x++) { block[(y * iWidth) + x] = piBlkResi[(y * uiStride) + x]; } } xTrMxN( channelBitDepth, block, coeff, iWidth, iHeight, useDST, maxLog2TrDynamicRange ); memcpy(psCoeff, coeff, (iWidth * iHeight * sizeof(TCoeff))); } /** Wrapper function between HM interface and core NxN inverse transform (2D) * \param channelBitDepth bit depth of channel * \param useDST * \param plCoef input data (transform coefficients) * \param pResidual output data (residual) * \param uiStride stride of input residual data * \param iWidth transform width * \param iHeight transform height * \param maxLog2TrDynamicRange */ Void TComTrQuant::xIT( const Int channelBitDepth, Bool useDST, TCoeff* plCoef, Pel* pResidual, UInt uiStride, Int iWidth, Int iHeight, const Int maxLog2TrDynamicRange ) { #if MATRIX_MULT if( iWidth == iHeight ) { xITr(channelBitDepth, plCoef, pResidual, uiStride, (UInt)iWidth, useDST, maxLog2TrDynamicRange); return; } #endif TCoeff block[ MAX_TU_SIZE * MAX_TU_SIZE ]; TCoeff coeff[ MAX_TU_SIZE * MAX_TU_SIZE ]; memcpy(coeff, plCoef, (iWidth * iHeight * sizeof(TCoeff))); xITrMxN( channelBitDepth, coeff, block, iWidth, iHeight, useDST, maxLog2TrDynamicRange ); for (Int y = 0; y < iHeight; y++) { for (Int x = 0; x < iWidth; x++) { pResidual[(y * uiStride) + x] = Pel(block[(y * iWidth) + x]); } } } /** Wrapper function between HM interface and core 4x4 transform skipping * \param piBlkResi input data (residual) * \param uiStride stride of input residual data * \param psCoeff output data (transform coefficients) * \param rTu reference to transform data * \param component colour component */ Void TComTrQuant::xTransformSkip( Pel* piBlkResi, UInt uiStride, TCoeff* psCoeff, TComTU &rTu, const ComponentID component ) { const TComRectangle &rect = rTu.getRect(component); const Int width = rect.width; const Int height = rect.height; const Int maxLog2TrDynamicRange = rTu.getCU()->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(component)); const Int channelBitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(toChannelType(component)); Int iTransformShift = getTransformShift(channelBitDepth, rTu.GetEquivalentLog2TrSize(component), maxLog2TrDynamicRange); if (rTu.getCU()->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag()) { iTransformShift = std::max(0, iTransformShift); } const Bool rotateResidual = rTu.isNonTransformedResidualRotated(component); const UInt uiSizeMinus1 = (width * height) - 1; if (iTransformShift >= 0) { for (UInt y = 0, coefficientIndex = 0; y < height; y++) { for (UInt x = 0; x < width; x++, coefficientIndex++) { psCoeff[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] = TCoeff(piBlkResi[(y * uiStride) + x]) << iTransformShift; } } } else //for very high bit depths { iTransformShift = -iTransformShift; const TCoeff offset = 1 << (iTransformShift - 1); for (UInt y = 0, coefficientIndex = 0; y < height; y++) { for (UInt x = 0; x < width; x++, coefficientIndex++) { psCoeff[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] = (TCoeff(piBlkResi[(y * uiStride) + x]) + offset) >> iTransformShift; } } } } /** Wrapper function between HM interface and core NxN transform skipping * \param plCoef input data (coefficients) * \param pResidual output data (residual) * \param uiStride stride of input residual data * \param rTu reference to transform data * \param component colour component ID */ Void TComTrQuant::xITransformSkip( TCoeff* plCoef, Pel* pResidual, UInt uiStride, TComTU &rTu, const ComponentID component ) { const TComRectangle &rect = rTu.getRect(component); const Int width = rect.width; const Int height = rect.height; const Int maxLog2TrDynamicRange = rTu.getCU()->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(component)); #if O0043_BEST_EFFORT_DECODING const Int channelBitDepth = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(toChannelType(component)); #else const Int channelBitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(toChannelType(component)); #endif Int iTransformShift = getTransformShift(channelBitDepth, rTu.GetEquivalentLog2TrSize(component), maxLog2TrDynamicRange); if (rTu.getCU()->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag()) { iTransformShift = std::max(0, iTransformShift); } const Bool rotateResidual = rTu.isNonTransformedResidualRotated(component); const UInt uiSizeMinus1 = (width * height) - 1; if (iTransformShift >= 0) { const TCoeff offset = iTransformShift==0 ? 0 : (1 << (iTransformShift - 1)); for (UInt y = 0, coefficientIndex = 0; y < height; y++) { for (UInt x = 0; x < width; x++, coefficientIndex++) { pResidual[(y * uiStride) + x] = Pel((plCoef[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] + offset) >> iTransformShift); } } } else //for very high bit depths { iTransformShift = -iTransformShift; for (UInt y = 0, coefficientIndex = 0; y < height; y++) { for (UInt x = 0; x < width; x++, coefficientIndex++) { pResidual[(y * uiStride) + x] = Pel(plCoef[rotateResidual ? (uiSizeMinus1 - coefficientIndex) : coefficientIndex] << iTransformShift); } } } } /** RDOQ with CABAC * \param rTu reference to transform data * \param plSrcCoeff pointer to input buffer * \param piDstCoeff reference to pointer to output buffer * \param piArlDstCoeff * \param uiAbsSum reference to absolute sum of quantized transform coefficient * \param compID colour component ID * \param cQP reference to quantization parameters * Rate distortion optimized quantization for entropy * coding engines using probability models like CABAC */ Void TComTrQuant::xRateDistOptQuant ( TComTU &rTu, TCoeff * plSrcCoeff, TCoeff * piDstCoeff, #if ADAPTIVE_QP_SELECTION TCoeff * piArlDstCoeff, #endif TCoeff &uiAbsSum, const ComponentID compID, const QpParam &cQP ) { const TComRectangle & rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; TComDataCU * pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const ChannelType channelType = toChannelType(compID); const UInt uiLog2TrSize = rTu.GetEquivalentLog2TrSize(compID); const Bool extendedPrecision = pcCU->getSlice()->getSPS()->getSpsRangeExtension().getExtendedPrecisionProcessingFlag(); const Int maxLog2TrDynamicRange = pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); const Int channelBitDepth = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType); /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller) * Then a QP+3 (sqrt(2)) or QP-3 (1/sqrt(2)) method could be used to get the required result */ // Represents scaling through forward transform Int iTransformShift = getTransformShift(channelBitDepth, uiLog2TrSize, maxLog2TrDynamicRange); if ((pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0) && extendedPrecision) { iTransformShift = std::max(0, iTransformShift); } const Bool bUseGolombRiceParameterAdaptation = pcCU->getSlice()->getSPS()->getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag(); const UInt initialGolombRiceParameter = m_pcEstBitsSbac->golombRiceAdaptationStatistics[rTu.getGolombRiceStatisticsIndex(compID)] / RExt__GOLOMB_RICE_INCREMENT_DIVISOR; UInt uiGoRiceParam = initialGolombRiceParameter; Double d64BlockUncodedCost = 0; const UInt uiLog2BlockWidth = g_aucConvertToBit[ uiWidth ] + 2; const UInt uiLog2BlockHeight = g_aucConvertToBit[ uiHeight ] + 2; const UInt uiMaxNumCoeff = uiWidth * uiHeight; assert(compIDgetPredictionMode(uiAbsPartIdx), compID); assert(scalingListType < SCALING_LIST_NUM); #if ADAPTIVE_QP_SELECTION memset(piArlDstCoeff, 0, sizeof(TCoeff) * uiMaxNumCoeff); #endif Double pdCostCoeff [ MAX_TU_SIZE * MAX_TU_SIZE ]; Double pdCostSig [ MAX_TU_SIZE * MAX_TU_SIZE ]; Double pdCostCoeff0[ MAX_TU_SIZE * MAX_TU_SIZE ]; memset( pdCostCoeff, 0, sizeof(Double) * uiMaxNumCoeff ); memset( pdCostSig, 0, sizeof(Double) * uiMaxNumCoeff ); Int rateIncUp [ MAX_TU_SIZE * MAX_TU_SIZE ]; Int rateIncDown [ MAX_TU_SIZE * MAX_TU_SIZE ]; Int sigRateDelta[ MAX_TU_SIZE * MAX_TU_SIZE ]; TCoeff deltaU [ MAX_TU_SIZE * MAX_TU_SIZE ]; memset( rateIncUp, 0, sizeof(Int ) * uiMaxNumCoeff ); memset( rateIncDown, 0, sizeof(Int ) * uiMaxNumCoeff ); memset( sigRateDelta, 0, sizeof(Int ) * uiMaxNumCoeff ); memset( deltaU, 0, sizeof(TCoeff) * uiMaxNumCoeff ); const Int iQBits = QUANT_SHIFT + cQP.per + iTransformShift; // Right shift of non-RDOQ quantizer; level = (coeff*uiQ + offset)>>q_bits const Double *const pdErrScale = getErrScaleCoeff(scalingListType, (uiLog2TrSize-2), cQP.rem); const Int *const piQCoef = getQuantCoeff(scalingListType, cQP.rem, (uiLog2TrSize-2)); const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (pcCU->getTransformSkip(uiAbsPartIdx, compID) != 0)); const Int defaultQuantisationCoefficient = g_quantScales[cQP.rem]; const Double defaultErrorScale = getErrScaleCoeffNoScalingList(scalingListType, (uiLog2TrSize-2), cQP.rem); const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; #if ADAPTIVE_QP_SELECTION Int iQBitsC = iQBits - ARL_C_PRECISION; Int iAddC = 1 << (iQBitsC-1); #endif TUEntropyCodingParameters codingParameters; getTUEntropyCodingParameters(codingParameters, rTu, compID); const UInt uiCGSize = (1 << MLS_CG_SIZE); Double pdCostCoeffGroupSig[ MLS_GRP_NUM ]; UInt uiSigCoeffGroupFlag[ MLS_GRP_NUM ]; Int iCGLastScanPos = -1; UInt uiCtxSet = 0; Int c1 = 1; Int c2 = 0; Double d64BaseCost = 0; Int iLastScanPos = -1; UInt c1Idx = 0; UInt c2Idx = 0; Int baseLevel; memset( pdCostCoeffGroupSig, 0, sizeof(Double) * MLS_GRP_NUM ); memset( uiSigCoeffGroupFlag, 0, sizeof(UInt) * MLS_GRP_NUM ); UInt uiCGNum = uiWidth * uiHeight >> MLS_CG_SIZE; Int iScanPos; coeffGroupRDStats rdStats; const UInt significanceMapContextOffset = getSignificanceMapContextOffset(compID); for (Int iCGScanPos = uiCGNum-1; iCGScanPos >= 0; iCGScanPos--) { UInt uiCGBlkPos = codingParameters.scanCG[ iCGScanPos ]; UInt uiCGPosY = uiCGBlkPos / codingParameters.widthInGroups; UInt uiCGPosX = uiCGBlkPos - (uiCGPosY * codingParameters.widthInGroups); memset( &rdStats, 0, sizeof (coeffGroupRDStats)); const Int patternSigCtx = TComTrQuant::calcPatternSigCtx(uiSigCoeffGroupFlag, uiCGPosX, uiCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups); for (Int iScanPosinCG = uiCGSize-1; iScanPosinCG >= 0; iScanPosinCG--) { iScanPos = iCGScanPos*uiCGSize + iScanPosinCG; //===== quantization ===== UInt uiBlkPos = codingParameters.scan[iScanPos]; // set coeff const Int quantisationCoefficient = (enableScalingLists) ? piQCoef [uiBlkPos] : defaultQuantisationCoefficient; const Double errorScale = (enableScalingLists) ? pdErrScale[uiBlkPos] : defaultErrorScale; const Int64 tmpLevel = Int64(abs(plSrcCoeff[ uiBlkPos ])) * quantisationCoefficient; const Intermediate_Int lLevelDouble = (Intermediate_Int)min(tmpLevel, std::numeric_limits::max() - (Intermediate_Int(1) << (iQBits - 1))); #if ADAPTIVE_QP_SELECTION if( m_bUseAdaptQpSelect ) { piArlDstCoeff[uiBlkPos] = (TCoeff)(( lLevelDouble + iAddC) >> iQBitsC ); } #endif const UInt uiMaxAbsLevel = std::min(UInt(entropyCodingMaximum), UInt((lLevelDouble + (Intermediate_Int(1) << (iQBits - 1))) >> iQBits)); const Double dErr = Double( lLevelDouble ); pdCostCoeff0[ iScanPos ] = dErr * dErr * errorScale; d64BlockUncodedCost += pdCostCoeff0[ iScanPos ]; piDstCoeff[ uiBlkPos ] = uiMaxAbsLevel; if ( uiMaxAbsLevel > 0 && iLastScanPos < 0 ) { iLastScanPos = iScanPos; uiCtxSet = getContextSetIndex(compID, (iScanPos >> MLS_CG_SIZE), 0); iCGLastScanPos = iCGScanPos; } if ( iLastScanPos >= 0 ) { //===== coefficient level estimation ===== UInt uiLevel; UInt uiOneCtx = (NUM_ONE_FLAG_CTX_PER_SET * uiCtxSet) + c1; UInt uiAbsCtx = (NUM_ABS_FLAG_CTX_PER_SET * uiCtxSet) + c2; if( iScanPos == iLastScanPos ) { uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], lLevelDouble, uiMaxAbsLevel, significanceMapContextOffset, uiOneCtx, uiAbsCtx, uiGoRiceParam, c1Idx, c2Idx, iQBits, errorScale, 1, extendedPrecision, maxLog2TrDynamicRange ); } else { UShort uiCtxSig = significanceMapContextOffset + getSigCtxInc( patternSigCtx, codingParameters, iScanPos, uiLog2BlockWidth, uiLog2BlockHeight, channelType ); uiLevel = xGetCodedLevel( pdCostCoeff[ iScanPos ], pdCostCoeff0[ iScanPos ], pdCostSig[ iScanPos ], lLevelDouble, uiMaxAbsLevel, uiCtxSig, uiOneCtx, uiAbsCtx, uiGoRiceParam, c1Idx, c2Idx, iQBits, errorScale, 0, extendedPrecision, maxLog2TrDynamicRange ); sigRateDelta[ uiBlkPos ] = m_pcEstBitsSbac->significantBits[ uiCtxSig ][ 1 ] - m_pcEstBitsSbac->significantBits[ uiCtxSig ][ 0 ]; } deltaU[ uiBlkPos ] = TCoeff((lLevelDouble - (Intermediate_Int(uiLevel) << iQBits)) >> (iQBits-8)); if( uiLevel > 0 ) { Int rateNow = xGetICRate( uiLevel, uiOneCtx, uiAbsCtx, uiGoRiceParam, c1Idx, c2Idx, extendedPrecision, maxLog2TrDynamicRange ); rateIncUp [ uiBlkPos ] = xGetICRate( uiLevel+1, uiOneCtx, uiAbsCtx, uiGoRiceParam, c1Idx, c2Idx, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; rateIncDown [ uiBlkPos ] = xGetICRate( uiLevel-1, uiOneCtx, uiAbsCtx, uiGoRiceParam, c1Idx, c2Idx, extendedPrecision, maxLog2TrDynamicRange ) - rateNow; } else // uiLevel == 0 { rateIncUp [ uiBlkPos ] = m_pcEstBitsSbac->m_greaterOneBits[ uiOneCtx ][ 0 ]; } piDstCoeff[ uiBlkPos ] = uiLevel; d64BaseCost += pdCostCoeff [ iScanPos ]; baseLevel = (c1Idx < C1FLAG_NUMBER) ? (2 + (c2Idx < C2FLAG_NUMBER)) : 1; if( uiLevel >= baseLevel ) { if (uiLevel > 3*(1<((uiGoRiceParam + 1), 4)); } } if ( uiLevel >= 1) { c1Idx ++; } //===== update bin model ===== if( uiLevel > 1 ) { c1 = 0; c2 += (c2 < 2); c2Idx ++; } else if( (c1 < 3) && (c1 > 0) && uiLevel) { c1++; } //===== context set update ===== if( ( iScanPos % uiCGSize == 0 ) && ( iScanPos > 0 ) ) { uiCtxSet = getContextSetIndex(compID, ((iScanPos - 1) >> MLS_CG_SIZE), (c1 == 0)); //(iScanPos - 1) because we do this **before** entering the final group c1 = 1; c2 = 0; c1Idx = 0; c2Idx = 0; uiGoRiceParam = initialGolombRiceParameter; } } else { d64BaseCost += pdCostCoeff0[ iScanPos ]; } rdStats.d64SigCost += pdCostSig[ iScanPos ]; if (iScanPosinCG == 0 ) { rdStats.d64SigCost_0 = pdCostSig[ iScanPos ]; } if (piDstCoeff[ uiBlkPos ] ) { uiSigCoeffGroupFlag[ uiCGBlkPos ] = 1; rdStats.d64CodedLevelandDist += pdCostCoeff[ iScanPos ] - pdCostSig[ iScanPos ]; rdStats.d64UncodedDist += pdCostCoeff0[ iScanPos ]; if ( iScanPosinCG != 0 ) { rdStats.iNNZbeforePos0++; } } } //end for (iScanPosinCG) if (iCGLastScanPos >= 0) { if( iCGScanPos ) { if (uiSigCoeffGroupFlag[ uiCGBlkPos ] == 0) { UInt uiCtxSig = getSigCoeffGroupCtxInc( uiSigCoeffGroupFlag, uiCGPosX, uiCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups ); d64BaseCost += xGetRateSigCoeffGroup(0, uiCtxSig) - rdStats.d64SigCost;; pdCostCoeffGroupSig[ iCGScanPos ] = xGetRateSigCoeffGroup(0, uiCtxSig); } else { if (iCGScanPos < iCGLastScanPos) //skip the last coefficient group, which will be handled together with last position below. { if ( rdStats.iNNZbeforePos0 == 0 ) { d64BaseCost -= rdStats.d64SigCost_0; rdStats.d64SigCost -= rdStats.d64SigCost_0; } // rd-cost if SigCoeffGroupFlag = 0, initialization Double d64CostZeroCG = d64BaseCost; // add SigCoeffGroupFlag cost to total cost UInt uiCtxSig = getSigCoeffGroupCtxInc( uiSigCoeffGroupFlag, uiCGPosX, uiCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups ); if (iCGScanPos < iCGLastScanPos) { d64BaseCost += xGetRateSigCoeffGroup(1, uiCtxSig); d64CostZeroCG += xGetRateSigCoeffGroup(0, uiCtxSig); pdCostCoeffGroupSig[ iCGScanPos ] = xGetRateSigCoeffGroup(1, uiCtxSig); } // try to convert the current coeff group from non-zero to all-zero d64CostZeroCG += rdStats.d64UncodedDist; // distortion for resetting non-zero levels to zero levels d64CostZeroCG -= rdStats.d64CodedLevelandDist; // distortion and level cost for keeping all non-zero levels d64CostZeroCG -= rdStats.d64SigCost; // sig cost for all coeffs, including zero levels and non-zerl levels // if we can save cost, change this block to all-zero block if ( d64CostZeroCG < d64BaseCost ) { uiSigCoeffGroupFlag[ uiCGBlkPos ] = 0; d64BaseCost = d64CostZeroCG; if (iCGScanPos < iCGLastScanPos) { pdCostCoeffGroupSig[ iCGScanPos ] = xGetRateSigCoeffGroup(0, uiCtxSig); } // reset coeffs to 0 in this block for (Int iScanPosinCG = uiCGSize-1; iScanPosinCG >= 0; iScanPosinCG--) { iScanPos = iCGScanPos*uiCGSize + iScanPosinCG; UInt uiBlkPos = codingParameters.scan[ iScanPos ]; if (piDstCoeff[ uiBlkPos ]) { piDstCoeff [ uiBlkPos ] = 0; pdCostCoeff[ iScanPos ] = pdCostCoeff0[ iScanPos ]; pdCostSig [ iScanPos ] = 0; } } } // end if ( d64CostAllZeros < d64BaseCost ) } } // end if if (uiSigCoeffGroupFlag[ uiCGBlkPos ] == 0) } else { uiSigCoeffGroupFlag[ uiCGBlkPos ] = 1; } } } //end for (iCGScanPos) //===== estimate last position ===== if ( iLastScanPos < 0 ) { return; } Double d64BestCost = 0; Int ui16CtxCbf = 0; Int iBestLastIdxP1 = 0; if( !pcCU->isIntra( uiAbsPartIdx ) && isLuma(compID) && pcCU->getTransformIdx( uiAbsPartIdx ) == 0 ) { ui16CtxCbf = 0; d64BestCost = d64BlockUncodedCost + xGetICost( m_pcEstBitsSbac->blockRootCbpBits[ ui16CtxCbf ][ 0 ] ); d64BaseCost += xGetICost( m_pcEstBitsSbac->blockRootCbpBits[ ui16CtxCbf ][ 1 ] ); } else { ui16CtxCbf = pcCU->getCtxQtCbf( rTu, channelType ); ui16CtxCbf += getCBFContextOffset(compID); d64BestCost = d64BlockUncodedCost + xGetICost( m_pcEstBitsSbac->blockCbpBits[ ui16CtxCbf ][ 0 ] ); d64BaseCost += xGetICost( m_pcEstBitsSbac->blockCbpBits[ ui16CtxCbf ][ 1 ] ); } Bool bFoundLast = false; for (Int iCGScanPos = iCGLastScanPos; iCGScanPos >= 0; iCGScanPos--) { UInt uiCGBlkPos = codingParameters.scanCG[ iCGScanPos ]; d64BaseCost -= pdCostCoeffGroupSig [ iCGScanPos ]; if (uiSigCoeffGroupFlag[ uiCGBlkPos ]) { for (Int iScanPosinCG = uiCGSize-1; iScanPosinCG >= 0; iScanPosinCG--) { iScanPos = iCGScanPos*uiCGSize + iScanPosinCG; if (iScanPos > iLastScanPos) { continue; } UInt uiBlkPos = codingParameters.scan[iScanPos]; if( piDstCoeff[ uiBlkPos ] ) { UInt uiPosY = uiBlkPos >> uiLog2BlockWidth; UInt uiPosX = uiBlkPos - ( uiPosY << uiLog2BlockWidth ); Double d64CostLast= codingParameters.scanType == SCAN_VER ? xGetRateLast( uiPosY, uiPosX, compID ) : xGetRateLast( uiPosX, uiPosY, compID ); Double totalCost = d64BaseCost + d64CostLast - pdCostSig[ iScanPos ]; if( totalCost < d64BestCost ) { iBestLastIdxP1 = iScanPos + 1; d64BestCost = totalCost; } if( piDstCoeff[ uiBlkPos ] > 1 ) { bFoundLast = true; break; } d64BaseCost -= pdCostCoeff[ iScanPos ]; d64BaseCost += pdCostCoeff0[ iScanPos ]; } else { d64BaseCost -= pdCostSig[ iScanPos ]; } } //end for if (bFoundLast) { break; } } // end if (uiSigCoeffGroupFlag[ uiCGBlkPos ]) } // end for for ( Int scanPos = 0; scanPos < iBestLastIdxP1; scanPos++ ) { Int blkPos = codingParameters.scan[ scanPos ]; TCoeff level = piDstCoeff[ blkPos ]; uiAbsSum += level; piDstCoeff[ blkPos ] = ( plSrcCoeff[ blkPos ] < 0 ) ? -level : level; } //===== clean uncoded coefficients ===== for ( Int scanPos = iBestLastIdxP1; scanPos <= iLastScanPos; scanPos++ ) { piDstCoeff[ codingParameters.scan[ scanPos ] ] = 0; } if( pcCU->getSlice()->getPPS()->getSignDataHidingEnabledFlag() && uiAbsSum>=2) { const Double inverseQuantScale = Double(g_invQuantScales[cQP.rem]); Int64 rdFactor = (Int64)(inverseQuantScale * inverseQuantScale * (1 << (2 * cQP.per)) / m_dLambda / 16 / (1 << (2 * DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth - 8))) + 0.5); Int lastCG = -1; Int absSum = 0 ; Int n ; for( Int subSet = (uiWidth*uiHeight-1) >> MLS_CG_SIZE; subSet >= 0; subSet-- ) { Int subPos = subSet << MLS_CG_SIZE; Int firstNZPosInCG=uiCGSize , lastNZPosInCG=-1 ; absSum = 0 ; for(n = uiCGSize-1; n >= 0; --n ) { if( piDstCoeff[ codingParameters.scan[ n + subPos ]] ) { lastNZPosInCG = n; break; } } for(n = 0; n =0 && lastCG==-1) { lastCG = 1; } if( lastNZPosInCG-firstNZPosInCG>=SBH_THRESHOLD ) { UInt signbit = (piDstCoeff[codingParameters.scan[subPos+firstNZPosInCG]]>0?0:1); if( signbit!=(absSum&0x1) ) // hide but need tune { // calculate the cost Int64 minCostInc = std::numeric_limits::max(), curCost = std::numeric_limits::max(); Int minPos = -1, finalChange = 0, curChange = 0; for( n = (lastCG==1?lastNZPosInCG:uiCGSize-1) ; n >= 0; --n ) { UInt uiBlkPos = codingParameters.scan[ n + subPos ]; if(piDstCoeff[ uiBlkPos ] != 0 ) { Int64 costUp = rdFactor * ( - deltaU[uiBlkPos] ) + rateIncUp[uiBlkPos]; Int64 costDown = rdFactor * ( deltaU[uiBlkPos] ) + rateIncDown[uiBlkPos] - ((abs(piDstCoeff[uiBlkPos]) == 1) ? sigRateDelta[uiBlkPos] : 0); if(lastCG==1 && lastNZPosInCG==n && abs(piDstCoeff[uiBlkPos])==1) { costDown -= (4<<15); } if(costUp::max(); } else { curCost = costDown; } } } else { curCost = rdFactor * ( - (abs(deltaU[uiBlkPos])) ) + (1<<15) + rateIncUp[uiBlkPos] + sigRateDelta[uiBlkPos] ; curChange = 1 ; if(n=0?0:1); if(thissignbit != signbit ) { curCost = std::numeric_limits::max(); } } } if( curCost=0) { piDstCoeff[minPos] += finalChange ; } else { piDstCoeff[minPos] -= finalChange ; } } } if(lastCG==1) { lastCG=0 ; } } } } /** Pattern decision for context derivation process of significant_coeff_flag * \param sigCoeffGroupFlag pointer to prior coded significant coeff group * \param uiCGPosX column of current coefficient group * \param uiCGPosY row of current coefficient group * \param widthInGroups width of the block * \param heightInGroups height of the block * \returns pattern for current coefficient group */ Int TComTrQuant::calcPatternSigCtx( const UInt* sigCoeffGroupFlag, UInt uiCGPosX, UInt uiCGPosY, UInt widthInGroups, UInt heightInGroups ) { if ((widthInGroups <= 1) && (heightInGroups <= 1)) { return 0; } const Bool rightAvailable = uiCGPosX < (widthInGroups - 1); const Bool belowAvailable = uiCGPosY < (heightInGroups - 1); UInt sigRight = 0; UInt sigLower = 0; if (rightAvailable) { sigRight = ((sigCoeffGroupFlag[ (uiCGPosY * widthInGroups) + uiCGPosX + 1 ] != 0) ? 1 : 0); } if (belowAvailable) { sigLower = ((sigCoeffGroupFlag[ (uiCGPosY + 1) * widthInGroups + uiCGPosX ] != 0) ? 1 : 0); } return sigRight + (sigLower << 1); } /** Context derivation process of coeff_abs_significant_flag * \param patternSigCtx pattern for current coefficient group * \param codingParameters coding parameters for the TU (includes the scan) * \param scanPosition current position in scan order * \param log2BlockWidth log2 width of the block * \param log2BlockHeight log2 height of the block * \param chanType channel type (CHANNEL_TYPE_LUMA/CHROMA) * \returns ctxInc for current scan position */ Int TComTrQuant::getSigCtxInc ( Int patternSigCtx, const TUEntropyCodingParameters &codingParameters, const Int scanPosition, const Int log2BlockWidth, const Int log2BlockHeight, const ChannelType chanType) { if (codingParameters.firstSignificanceMapContext == significanceMapContextSetStart[chanType][CONTEXT_TYPE_SINGLE]) { //single context mode return significanceMapContextSetStart[chanType][CONTEXT_TYPE_SINGLE]; } const UInt rasterPosition = codingParameters.scan[scanPosition]; const UInt posY = rasterPosition >> log2BlockWidth; const UInt posX = rasterPosition - (posY << log2BlockWidth); if ((posX + posY) == 0) { return 0; //special case for the DC context variable } Int offset = MAX_INT; if ((log2BlockWidth == 2) && (log2BlockHeight == 2)) //4x4 { offset = ctxIndMap4x4[ (4 * posY) + posX ]; } else { Int cnt = 0; switch (patternSigCtx) { //------------------ case 0: //neither neighbouring group is significant { const Int posXinSubset = posX & ((1 << MLS_CG_LOG2_WIDTH) - 1); const Int posYinSubset = posY & ((1 << MLS_CG_LOG2_HEIGHT) - 1); const Int posTotalInSubset = posXinSubset + posYinSubset; //first N coefficients in scan order use 2; the next few use 1; the rest use 0. const UInt context1Threshold = NEIGHBOURHOOD_00_CONTEXT_1_THRESHOLD_4x4; const UInt context2Threshold = NEIGHBOURHOOD_00_CONTEXT_2_THRESHOLD_4x4; cnt = (posTotalInSubset >= context1Threshold) ? 0 : ((posTotalInSubset >= context2Threshold) ? 1 : 2); } break; //------------------ case 1: //right group is significant, below is not { const Int posYinSubset = posY & ((1 << MLS_CG_LOG2_HEIGHT) - 1); const Int groupHeight = 1 << MLS_CG_LOG2_HEIGHT; cnt = (posYinSubset >= (groupHeight >> 1)) ? 0 : ((posYinSubset >= (groupHeight >> 2)) ? 1 : 2); //top quarter uses 2; second-from-top quarter uses 1; bottom half uses 0 } break; //------------------ case 2: //below group is significant, right is not { const Int posXinSubset = posX & ((1 << MLS_CG_LOG2_WIDTH) - 1); const Int groupWidth = 1 << MLS_CG_LOG2_WIDTH; cnt = (posXinSubset >= (groupWidth >> 1)) ? 0 : ((posXinSubset >= (groupWidth >> 2)) ? 1 : 2); //left quarter uses 2; second-from-left quarter uses 1; right half uses 0 } break; //------------------ case 3: //both neighbouring groups are significant { cnt = 2; } break; //------------------ default: std::cerr << "ERROR: Invalid patternSigCtx \"" << Int(patternSigCtx) << "\" in getSigCtxInc" << std::endl; exit(1); break; } //------------------------------------------------ const Bool notFirstGroup = ((posX >> MLS_CG_LOG2_WIDTH) + (posY >> MLS_CG_LOG2_HEIGHT)) > 0; offset = (notFirstGroup ? notFirstGroupNeighbourhoodContextOffset[chanType] : 0) + cnt; } return codingParameters.firstSignificanceMapContext + offset; } /** Get the best level in RD sense * * \returns best quantized transform level for given scan position * * This method calculates the best quantized transform level for a given scan position. */ __inline UInt TComTrQuant::xGetCodedLevel ( Double& rd64CodedCost, //< reference to coded cost Double& rd64CodedCost0, //< reference to cost when coefficient is 0 Double& rd64CodedCostSig, //< rd64CodedCostSig reference to cost of significant coefficient Intermediate_Int lLevelDouble, //< reference to unscaled quantized level UInt uiMaxAbsLevel, //< scaled quantized level UShort ui16CtxNumSig, //< current ctxInc for coeff_abs_significant_flag UShort ui16CtxNumOne, //< current ctxInc for coeff_abs_level_greater1 (1st bin of coeff_abs_level_minus1 in AVC) UShort ui16CtxNumAbs, //< current ctxInc for coeff_abs_level_greater2 (remaining bins of coeff_abs_level_minus1 in AVC) UShort ui16AbsGoRice, //< current Rice parameter for coeff_abs_level_minus3 UInt c1Idx, //< UInt c2Idx, //< Int iQBits, //< quantization step size Double errorScale, //< Bool bLast, //< indicates if the coefficient is the last significant Bool useLimitedPrefixLength, //< const Int maxLog2TrDynamicRange //< ) const { Double dCurrCostSig = 0; UInt uiBestAbsLevel = 0; if( !bLast && uiMaxAbsLevel < 3 ) { rd64CodedCostSig = xGetRateSigCoef( 0, ui16CtxNumSig ); rd64CodedCost = rd64CodedCost0 + rd64CodedCostSig; if( uiMaxAbsLevel == 0 ) { return uiBestAbsLevel; } } else { rd64CodedCost = MAX_DOUBLE; } if( !bLast ) { dCurrCostSig = xGetRateSigCoef( 1, ui16CtxNumSig ); } UInt uiMinAbsLevel = ( uiMaxAbsLevel > 1 ? uiMaxAbsLevel - 1 : 1 ); for( Int uiAbsLevel = uiMaxAbsLevel; uiAbsLevel >= uiMinAbsLevel ; uiAbsLevel-- ) { Double dErr = Double( lLevelDouble - ( Intermediate_Int(uiAbsLevel) << iQBits ) ); Double dCurrCost = dErr * dErr * errorScale + xGetICost( xGetICRate( uiAbsLevel, ui16CtxNumOne, ui16CtxNumAbs, ui16AbsGoRice, c1Idx, c2Idx, useLimitedPrefixLength, maxLog2TrDynamicRange ) ); dCurrCost += dCurrCostSig; if( dCurrCost < rd64CodedCost ) { uiBestAbsLevel = uiAbsLevel; rd64CodedCost = dCurrCost; rd64CodedCostSig = dCurrCostSig; } } return uiBestAbsLevel; } /** Calculates the cost for specific absolute transform level * \param uiAbsLevel scaled quantized level * \param ui16CtxNumOne current ctxInc for coeff_abs_level_greater1 (1st bin of coeff_abs_level_minus1 in AVC) * \param ui16CtxNumAbs current ctxInc for coeff_abs_level_greater2 (remaining bins of coeff_abs_level_minus1 in AVC) * \param ui16AbsGoRice Rice parameter for coeff_abs_level_minus3 * \param c1Idx * \param c2Idx * \param useLimitedPrefixLength * \param maxLog2TrDynamicRange * \returns cost of given absolute transform level */ __inline Int TComTrQuant::xGetICRate ( const UInt uiAbsLevel, const UShort ui16CtxNumOne, const UShort ui16CtxNumAbs, const UShort ui16AbsGoRice, const UInt c1Idx, const UInt c2Idx, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ) const { Int iRate = Int(xGetIEPRate()); // cost of sign bit UInt baseLevel = (c1Idx < C1FLAG_NUMBER) ? (2 + (c2Idx < C2FLAG_NUMBER)) : 1; if ( uiAbsLevel >= baseLevel ) { UInt symbol = uiAbsLevel - baseLevel; UInt length; if (symbol < (COEF_REMAIN_BIN_REDUCTION << ui16AbsGoRice)) { length = symbol>>ui16AbsGoRice; iRate += (length+1+ui16AbsGoRice)<< 15; } else if (useLimitedPrefixLength) { const UInt maximumPrefixLength = (32 - (COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange)); UInt prefixLength = 0; UInt suffix = (symbol >> ui16AbsGoRice) - COEF_REMAIN_BIN_REDUCTION; while ((prefixLength < maximumPrefixLength) && (suffix > ((2 << prefixLength) - 2))) { prefixLength++; } const UInt suffixLength = (prefixLength == maximumPrefixLength) ? (maxLog2TrDynamicRange - ui16AbsGoRice) : (prefixLength + 1/*separator*/); iRate += (COEF_REMAIN_BIN_REDUCTION + prefixLength + suffixLength + ui16AbsGoRice) << 15; } else { length = ui16AbsGoRice; symbol = symbol - ( COEF_REMAIN_BIN_REDUCTION << ui16AbsGoRice); while (symbol >= (1<m_greaterOneBits[ ui16CtxNumOne ][ 1 ]; if (c2Idx < C2FLAG_NUMBER) { iRate += m_pcEstBitsSbac->m_levelAbsBits[ ui16CtxNumAbs ][ 1 ]; } } } else if( uiAbsLevel == 1 ) { iRate += m_pcEstBitsSbac->m_greaterOneBits[ ui16CtxNumOne ][ 0 ]; } else if( uiAbsLevel == 2 ) { iRate += m_pcEstBitsSbac->m_greaterOneBits[ ui16CtxNumOne ][ 1 ]; iRate += m_pcEstBitsSbac->m_levelAbsBits[ ui16CtxNumAbs ][ 0 ]; } else { iRate = 0; } return iRate; } __inline Double TComTrQuant::xGetRateSigCoeffGroup ( UShort uiSignificanceCoeffGroup, UShort ui16CtxNumSig ) const { return xGetICost( m_pcEstBitsSbac->significantCoeffGroupBits[ ui16CtxNumSig ][ uiSignificanceCoeffGroup ] ); } /** Calculates the cost of signaling the last significant coefficient in the block * \param uiPosX X coordinate of the last significant coefficient * \param uiPosY Y coordinate of the last significant coefficient * \param component colour component ID * \returns cost of last significant coefficient */ /* * \param uiWidth width of the transform unit (TU) */ __inline Double TComTrQuant::xGetRateLast ( const UInt uiPosX, const UInt uiPosY, const ComponentID component ) const { UInt uiCtxX = g_uiGroupIdx[uiPosX]; UInt uiCtxY = g_uiGroupIdx[uiPosY]; Double uiCost = m_pcEstBitsSbac->lastXBits[toChannelType(component)][ uiCtxX ] + m_pcEstBitsSbac->lastYBits[toChannelType(component)][ uiCtxY ]; if( uiCtxX > 3 ) { uiCost += xGetIEPRate() * ((uiCtxX-2)>>1); } if( uiCtxY > 3 ) { uiCost += xGetIEPRate() * ((uiCtxY-2)>>1); } return xGetICost( uiCost ); } __inline Double TComTrQuant::xGetRateSigCoef ( UShort uiSignificance, UShort ui16CtxNumSig ) const { return xGetICost( m_pcEstBitsSbac->significantBits[ ui16CtxNumSig ][ uiSignificance ] ); } /** Get the cost for a specific rate * \param dRate rate of a bit * \returns cost at the specific rate */ __inline Double TComTrQuant::xGetICost ( Double dRate ) const { return m_dLambda * dRate; } /** Get the cost of an equal probable bit * \returns cost of equal probable bit */ __inline Double TComTrQuant::xGetIEPRate ( ) const { return 32768; } /** Context derivation process of coeff_abs_significant_flag * \param uiSigCoeffGroupFlag significance map of L1 * \param uiCGPosX column of current scan position * \param uiCGPosY row of current scan position * \param widthInGroups width of the block * \param heightInGroups height of the block * \returns ctxInc for current scan position */ UInt TComTrQuant::getSigCoeffGroupCtxInc (const UInt* uiSigCoeffGroupFlag, const UInt uiCGPosX, const UInt uiCGPosY, const UInt widthInGroups, const UInt heightInGroups) { UInt sigRight = 0; UInt sigLower = 0; if (uiCGPosX < (widthInGroups - 1)) { sigRight = ((uiSigCoeffGroupFlag[ (uiCGPosY * widthInGroups) + uiCGPosX + 1 ] != 0) ? 1 : 0); } if (uiCGPosY < (heightInGroups - 1)) { sigLower = ((uiSigCoeffGroupFlag[ (uiCGPosY + 1) * widthInGroups + uiCGPosX ] != 0) ? 1 : 0); } return ((sigRight + sigLower) != 0) ? 1 : 0; } /** set quantized matrix coefficient for encode * \param scalingList quantized matrix address * \param format chroma format * \param maxLog2TrDynamicRange * \param bitDepths reference to bit depth array for all channels */ Void TComTrQuant::setScalingList(TComScalingList *scalingList, const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths) { const Int minimumQp = 0; const Int maximumQp = SCALING_LIST_REM_NUM; for(UInt size = 0; size < SCALING_LIST_SIZE_NUM; size++) { for(UInt list = 0; list < SCALING_LIST_NUM; list++) { for(Int qp = minimumQp; qp < maximumQp; qp++) { xSetScalingListEnc(scalingList,list,size,qp); xSetScalingListDec(*scalingList,list,size,qp); setErrScaleCoeff(list,size,qp,maxLog2TrDynamicRange, bitDepths); } } } } /** set quantized matrix coefficient for decode * \param scalingList quantized matrix address * \param format chroma format */ Void TComTrQuant::setScalingListDec(const TComScalingList &scalingList) { const Int minimumQp = 0; const Int maximumQp = SCALING_LIST_REM_NUM; for(UInt size = 0; size < SCALING_LIST_SIZE_NUM; size++) { for(UInt list = 0; list < SCALING_LIST_NUM; list++) { for(Int qp = minimumQp; qp < maximumQp; qp++) { xSetScalingListDec(scalingList,list,size,qp); } } } } /** set error scale coefficients * \param list list ID * \param size * \param qp quantization parameter * \param maxLog2TrDynamicRange * \param bitDepths reference to bit depth array for all channels */ Void TComTrQuant::setErrScaleCoeff(UInt list, UInt size, Int qp, const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths) { const UInt uiLog2TrSize = g_aucConvertToBit[ g_scalingListSizeX[size] ] + 2; const ChannelType channelType = ((list == 0) || (list == MAX_NUM_COMPONENT)) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA; const Int channelBitDepth = bitDepths.recon[channelType]; const Int iTransformShift = getTransformShift(channelBitDepth, uiLog2TrSize, maxLog2TrDynamicRange[channelType]); // Represents scaling through forward transform UInt i,uiMaxNumCoeff = g_scalingListSize[size]; Int *piQuantcoeff; Double *pdErrScale; piQuantcoeff = getQuantCoeff(list, qp,size); pdErrScale = getErrScaleCoeff(list, size, qp); Double dErrScale = (Double)(1<getScalingListAddress(sizeId,listId); quantcoeff = getQuantCoeff(listId, qp, sizeId); Int quantScales = g_quantScales[qp]; processScalingListEnc(coeff, quantcoeff, (quantScales << LOG2_SCALING_LIST_NEUTRAL_VALUE), height, width, ratio, min(MAX_MATRIX_SIZE_NUM, (Int)g_scalingListSizeX[sizeId]), scalingList->getScalingListDC(sizeId,listId)); } /** set quantized matrix coefficient for decode * \param scalingList quantaized matrix address * \param listId List index * \param sizeId size index * \param qp Quantization parameter * \param format chroma format */ Void TComTrQuant::xSetScalingListDec(const TComScalingList &scalingList, UInt listId, UInt sizeId, Int qp) { UInt width = g_scalingListSizeX[sizeId]; UInt height = g_scalingListSizeX[sizeId]; UInt ratio = g_scalingListSizeX[sizeId]/min(MAX_MATRIX_SIZE_NUM,(Int)g_scalingListSizeX[sizeId]); Int *dequantcoeff; const Int *coeff = scalingList.getScalingListAddress(sizeId,listId); dequantcoeff = getDequantCoeff(listId, qp, sizeId); Int invQuantScale = g_invQuantScales[qp]; processScalingListDec(coeff, dequantcoeff, invQuantScale, height, width, ratio, min(MAX_MATRIX_SIZE_NUM, (Int)g_scalingListSizeX[sizeId]), scalingList.getScalingListDC(sizeId,listId)); } /** set flat matrix value to quantized coefficient */ Void TComTrQuant::setFlatScalingList(const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths) { const Int minimumQp = 0; const Int maximumQp = SCALING_LIST_REM_NUM; for(UInt size = 0; size < SCALING_LIST_SIZE_NUM; size++) { for(UInt list = 0; list < SCALING_LIST_NUM; list++) { for(Int qp = minimumQp; qp < maximumQp; qp++) { xsetFlatScalingList(list,size,qp); setErrScaleCoeff(list,size,qp,maxLog2TrDynamicRange, bitDepths); } } } } /** set flat matrix value to quantized coefficient * \param list List ID * \param size size index * \param qp Quantization parameter * \param format chroma format */ Void TComTrQuant::xsetFlatScalingList(UInt list, UInt size, Int qp) { UInt i,num = g_scalingListSize[size]; Int *quantcoeff; Int *dequantcoeff; Int quantScales = g_quantScales [qp]; Int invQuantScales = g_invQuantScales[qp] << 4; quantcoeff = getQuantCoeff(list, qp, size); dequantcoeff = getDequantCoeff(list, qp, size); for(i=0;i 1) { quantcoeff[0] = quantScales / dc; } } /** set quantized matrix coefficient for decode * \param coeff quantaized matrix address * \param dequantcoeff quantaized matrix address * \param invQuantScales IQ(QP%6)) * \param height height * \param width width * \param ratio ratio for upscale * \param sizuNum matrix size * \param dc dc parameter */ Void TComTrQuant::processScalingListDec( const Int *coeff, Int *dequantcoeff, Int invQuantScales, UInt height, UInt width, UInt ratio, Int sizuNum, UInt dc) { for(UInt j=0;j 1) { dequantcoeff[0] = invQuantScales * dc; } } /** initialization process of scaling list array */ Void TComTrQuant::initScalingList() { for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(UInt qp = 0; qp < SCALING_LIST_REM_NUM; qp++) { for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) { m_quantCoef [sizeId][listId][qp] = new Int [g_scalingListSize[sizeId]]; m_dequantCoef [sizeId][listId][qp] = new Int [g_scalingListSize[sizeId]]; m_errScale [sizeId][listId][qp] = new Double [g_scalingListSize[sizeId]]; } // listID loop } } } /** destroy quantization matrix array */ Void TComTrQuant::destroyScalingList() { for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) { for(UInt qp = 0; qp < SCALING_LIST_REM_NUM; qp++) { if(m_quantCoef[sizeId][listId][qp]) { delete [] m_quantCoef[sizeId][listId][qp]; } if(m_dequantCoef[sizeId][listId][qp]) { delete [] m_dequantCoef[sizeId][listId][qp]; } if(m_errScale[sizeId][listId][qp]) { delete [] m_errScale[sizeId][listId][qp]; } } } } } Void TComTrQuant::transformSkipQuantOneSample(TComTU &rTu, const ComponentID compID, const TCoeff resiDiff, TCoeff* pcCoeff, const UInt uiPos, const QpParam &cQP, const Bool bUseHalfRoundingPoint) { TComDataCU *pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; const Int maxLog2TrDynamicRange = pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); const Int iTransformShift = getTransformShift(channelBitDepth, rTu.GetEquivalentLog2TrSize(compID), maxLog2TrDynamicRange); const Int scalingListType = getScalingListType(pcCU->getPredictionMode(uiAbsPartIdx), compID); const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true); const Int defaultQuantisationCoefficient = g_quantScales[cQP.rem]; assert( scalingListType < SCALING_LIST_NUM ); const Int *const piQuantCoeff = getQuantCoeff( scalingListType, cQP.rem, (rTu.GetEquivalentLog2TrSize(compID)-2) ); /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the * uiLog2TrSize applied in iTransformShift, such that the result is 1/sqrt(2) the required result (i.e. smaller) * Then a QP+3 (sqrt(2)) or QP-3 (1/sqrt(2)) method could be used to get the required result */ const Int iQBits = QUANT_SHIFT + cQP.per + iTransformShift; // QBits will be OK for any internal bit depth as the reduction in transform shift is balanced by an increase in Qp_per due to QpBDOffset const Int iAdd = ( bUseHalfRoundingPoint ? 256 : (pcCU->getSlice()->getSliceType() == I_SLICE ? 171 : 85) ) << (iQBits - 9); TCoeff transformedCoefficient; // transform-skip if (iTransformShift >= 0) { transformedCoefficient = resiDiff << iTransformShift; } else // for very high bit depths { const Int iTrShiftNeg = -iTransformShift; const Int offset = 1 << (iTrShiftNeg - 1); transformedCoefficient = ( resiDiff + offset ) >> iTrShiftNeg; } // quantization const TCoeff iSign = (transformedCoefficient < 0 ? -1: 1); const Int quantisationCoefficient = enableScalingLists ? piQuantCoeff[uiPos] : defaultQuantisationCoefficient; const Int64 tmpLevel = (Int64)abs(transformedCoefficient) * quantisationCoefficient; const TCoeff quantisedCoefficient = (TCoeff((tmpLevel + iAdd ) >> iQBits)) * iSign; const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; pcCoeff[ uiPos ] = Clip3( entropyCodingMinimum, entropyCodingMaximum, quantisedCoefficient ); } Void TComTrQuant::invTrSkipDeQuantOneSample( TComTU &rTu, ComponentID compID, TCoeff inSample, Pel &reconSample, const QpParam &cQP, UInt uiPos ) { TComDataCU *pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const TComRectangle &rect = rTu.getRect(compID); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; const Int QP_per = cQP.per; const Int QP_rem = cQP.rem; const Int maxLog2TrDynamicRange = pcCU->getSlice()->getSPS()->getMaxLog2TrDynamicRange(toChannelType(compID)); #if O0043_BEST_EFFORT_DECODING const Int channelBitDepth = pcCU->getSlice()->getSPS()->getStreamBitDepth(toChannelType(compID)); #else const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); #endif const Int iTransformShift = getTransformShift(channelBitDepth, rTu.GetEquivalentLog2TrSize(compID), maxLog2TrDynamicRange); const Int scalingListType = getScalingListType(pcCU->getPredictionMode(uiAbsPartIdx), compID); const Bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true); const UInt uiLog2TrSize = rTu.GetEquivalentLog2TrSize(compID); assert( scalingListType < SCALING_LIST_NUM ); const Int rightShift = (IQUANT_SHIFT - (iTransformShift + QP_per)) + (enableScalingLists ? LOG2_SCALING_LIST_NEUTRAL_VALUE : 0); const TCoeff transformMinimum = -(1 << maxLog2TrDynamicRange); const TCoeff transformMaximum = (1 << maxLog2TrDynamicRange) - 1; // Dequantisation TCoeff dequantisedSample; if(enableScalingLists) { const UInt dequantCoefBits = 1 + IQUANT_SHIFT + SCALING_LIST_BITS; const UInt targetInputBitDepth = std::min((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - dequantCoefBits)); const Intermediate_Int inputMinimum = -(1 << (targetInputBitDepth - 1)); const Intermediate_Int inputMaximum = (1 << (targetInputBitDepth - 1)) - 1; Int *piDequantCoef = getDequantCoeff(scalingListType,QP_rem,uiLog2TrSize-2); if(rightShift > 0) { const Intermediate_Int iAdd = 1 << (rightShift - 1); const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, inSample)); const Intermediate_Int iCoeffQ = ((Intermediate_Int(clipQCoef) * piDequantCoef[uiPos]) + iAdd ) >> rightShift; dequantisedSample = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } else { const Int leftShift = -rightShift; const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, inSample)); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * piDequantCoef[uiPos]) << leftShift; dequantisedSample = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } else { const Int scale = g_invQuantScales[QP_rem]; const Int scaleBits = (IQUANT_SHIFT + 1) ; const UInt targetInputBitDepth = std::min((maxLog2TrDynamicRange + 1), (((sizeof(Intermediate_Int) * 8) + rightShift) - scaleBits)); const Intermediate_Int inputMinimum = -(1 << (targetInputBitDepth - 1)); const Intermediate_Int inputMaximum = (1 << (targetInputBitDepth - 1)) - 1; if (rightShift > 0) { const Intermediate_Int iAdd = 1 << (rightShift - 1); const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, inSample)); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * scale + iAdd) >> rightShift; dequantisedSample = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } else { const Int leftShift = -rightShift; const TCoeff clipQCoef = TCoeff(Clip3(inputMinimum, inputMaximum, inSample)); const Intermediate_Int iCoeffQ = (Intermediate_Int(clipQCoef) * scale) << leftShift; dequantisedSample = TCoeff(Clip3(transformMinimum,transformMaximum,iCoeffQ)); } } // Inverse transform-skip if (iTransformShift >= 0) { const TCoeff offset = iTransformShift==0 ? 0 : (1 << (iTransformShift - 1)); reconSample = Pel(( dequantisedSample + offset ) >> iTransformShift); } else //for very high bit depths { const Int iTrShiftNeg = -iTransformShift; reconSample = Pel(dequantisedSample << iTrShiftNeg); } } Void TComTrQuant::crossComponentPrediction( TComTU & rTu, const ComponentID compID, const Pel * piResiL, const Pel * piResiC, Pel * piResiT, const Int width, const Int height, const Int strideL, const Int strideC, const Int strideT, const Bool reverse ) { const Pel *pResiL = piResiL; const Pel *pResiC = piResiC; Pel *pResiT = piResiT; TComDataCU *pCU = rTu.getCU(); const Int alpha = pCU->getCrossComponentPredictionAlpha( rTu.GetAbsPartIdxTU( compID ), compID ); const Int diffBitDepth = pCU->getSlice()->getSPS()->getDifferentialLumaChromaBitDepth(); for( Int y = 0; y < height; y++ ) { if (reverse) { // A constraint is to be added to the HEVC Standard to limit the size of pResiL and pResiC at this point. // The likely form of the constraint is to either restrict the values to CoeffMin to CoeffMax, // or to be representable in a bitDepthY+4 or bitDepthC+4 signed integer. // The result of the constraint is that for 8/10/12bit profiles, the input values // can be represented within a 16-bit Pel-type. #if RExt__HIGH_BIT_DEPTH_SUPPORT for( Int x = 0; x < width; x++ ) { pResiT[x] = pResiC[x] + (( alpha * rightShift( pResiL[x], diffBitDepth) ) >> 3); } #else const Int minPel=std::numeric_limits::min(); const Int maxPel=std::numeric_limits::max(); for( Int x = 0; x < width; x++ ) { pResiT[x] = Clip3(minPel, maxPel, pResiC[x] + (( alpha * rightShift(Int(pResiL[x]), diffBitDepth) ) >> 3)); } #endif } else { // Forward does not need clipping. Pel type should always be big enough. for( Int x = 0; x < width; x++ ) { pResiT[x] = pResiC[x] - (( alpha * rightShift(Int(pResiL[x]), diffBitDepth) ) >> 3); } } pResiL += strideL; pResiC += strideC; pResiT += strideT; } } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComTrQuant.h000066400000000000000000000404251442026013100206110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComTrQuant.h \brief transform and quantization class (header) */ #ifndef __TCOMTRQUANT__ #define __TCOMTRQUANT__ #include "CommonDef.h" #include "TComYuv.h" #include "TComDataCU.h" #include "TComChromaFormat.h" #include "ContextTables.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Constants // ==================================================================================================================== #define QP_BITS 15 // ==================================================================================================================== // Type definition // ==================================================================================================================== typedef struct { Int significantCoeffGroupBits[NUM_SIG_CG_FLAG_CTX][2 /*Flag = [0|1]*/]; Int significantBits[NUM_SIG_FLAG_CTX][2 /*Flag = [0|1]*/]; Int lastXBits[MAX_NUM_CHANNEL_TYPE][LAST_SIGNIFICANT_GROUPS]; Int lastYBits[MAX_NUM_CHANNEL_TYPE][LAST_SIGNIFICANT_GROUPS]; Int m_greaterOneBits[NUM_ONE_FLAG_CTX][2 /*Flag = [0|1]*/]; Int m_levelAbsBits[NUM_ABS_FLAG_CTX][2 /*Flag = [0|1]*/]; Int blockCbpBits[NUM_QT_CBF_CTX_SETS * NUM_QT_CBF_CTX_PER_SET][2 /*Flag = [0|1]*/]; Int blockRootCbpBits[4][2 /*Flag = [0|1]*/]; Int golombRiceAdaptationStatistics[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS]; } estBitsSbacStruct; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// QP struct struct QpParam { Int Qp; Int per; Int rem; QpParam(const Int qpy, const ChannelType chType, const Int qpBdOffset, const Int chromaQPOffset, const ChromaFormat chFmt ); QpParam(const TComDataCU &cu, const ComponentID compID); }; // END STRUCT DEFINITION QpParam /// transform and quantization class class TComTrQuant { public: TComTrQuant(); ~TComTrQuant(); // initialize class Void init ( UInt uiMaxTrSize, Bool useRDOQ = false, Bool useRDOQTS = false, Bool useSelectiveRDOQ = false, Bool bEnc = false, Bool useTransformSkipFast = false #if ADAPTIVE_QP_SELECTION , Bool bUseAdaptQpSelect = false #endif ); // transform & inverse transform functions Void transformNxN( TComTU & rTu, const ComponentID compID, Pel * pcResidual, const UInt uiStride, TCoeff * rpcCoeff, #if ADAPTIVE_QP_SELECTION TCoeff * rpcArlCoeff, #endif TCoeff & uiAbsSum, const QpParam & cQP ); Void invTransformNxN( TComTU & rTu, const ComponentID compID, Pel *pcResidual, const UInt uiStride, TCoeff * pcCoeff, const QpParam & cQP DEBUG_STRING_FN_DECLAREP(psDebug)); Void invRecurTransformNxN ( const ComponentID compID, TComYuv *pResidual, TComTU &rTu ); Void rdpcmNxN ( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride, const QpParam& cQP, TCoeff* pcCoeff, TCoeff &uiAbsSum, RDPCMMode& rdpcmMode ); Void invRdpcmNxN( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride ); Void applyForwardRDPCM( TComTU& rTu, const ComponentID compID, Pel* pcResidual, const UInt uiStride, const QpParam& cQP, TCoeff* pcCoeff, TCoeff &uiAbsSum, const RDPCMMode mode ); // Misc functions #if RDOQ_CHROMA_LAMBDA Void setLambdas(const Double lambdas[MAX_NUM_COMPONENT]) { for (UInt component = 0; component < MAX_NUM_COMPONENT; component++) m_lambdas[component] = lambdas[component]; } Void selectLambda(const ComponentID compIdx) { m_dLambda = m_lambdas[compIdx]; } #else Void setLambda(Double dLambda) { m_dLambda = dLambda;} #endif Void setRDOQOffset( UInt uiRDOQOffset ) { m_uiRDOQOffset = uiRDOQOffset; } estBitsSbacStruct* m_pcEstBitsSbac; static Int calcPatternSigCtx( const UInt* sigCoeffGroupFlag, UInt uiCGPosX, UInt uiCGPosY, UInt widthInGroups, UInt heightInGroups ); static Int getSigCtxInc ( Int patternSigCtx, const TUEntropyCodingParameters &codingParameters, const Int scanPosition, const Int log2BlockWidth, const Int log2BlockHeight, const ChannelType chanType ); static UInt getSigCoeffGroupCtxInc (const UInt* uiSigCoeffGroupFlag, const UInt uiCGPosX, const UInt uiCGPosY, const UInt widthInGroups, const UInt heightInGroups); Void initScalingList (); Void destroyScalingList (); Void setErrScaleCoeff ( UInt list, UInt size, Int qp, const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths ); Double* getErrScaleCoeff ( UInt list, UInt size, Int qp ) { return m_errScale [size][list][qp]; }; //!< get Error Scale Coefficent Double& getErrScaleCoeffNoScalingList ( UInt list, UInt size, Int qp ) { return m_errScaleNoScalingList[size][list][qp]; }; //!< get Error Scale Coefficent Int* getQuantCoeff ( UInt list, Int qp, UInt size ) { return m_quantCoef [size][list][qp]; }; //!< get Quant Coefficent Int* getDequantCoeff ( UInt list, Int qp, UInt size ) { return m_dequantCoef [size][list][qp]; }; //!< get DeQuant Coefficent Void setUseScalingList ( Bool bUseScalingList){ m_scalingListEnabledFlag = bUseScalingList; }; Bool getUseScalingList (const UInt width, const UInt height, const Bool isTransformSkip){ return m_scalingListEnabledFlag && (!isTransformSkip || ((width == 4) && (height == 4))); }; Void setFlatScalingList (const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths); Void xsetFlatScalingList ( UInt list, UInt size, Int qp); Void xSetScalingListEnc ( TComScalingList *scalingList, UInt list, UInt size, Int qp); Void xSetScalingListDec ( const TComScalingList &scalingList, UInt list, UInt size, Int qp); Void setScalingList ( TComScalingList *scalingList, const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE], const BitDepths &bitDepths); Void setScalingListDec ( const TComScalingList &scalingList); Void processScalingListEnc( Int *coeff, Int *quantcoeff, Int quantScales, UInt height, UInt width, UInt ratio, Int sizuNum, UInt dc); Void processScalingListDec( const Int *coeff, Int *dequantcoeff, Int invQuantScales, UInt height, UInt width, UInt ratio, Int sizuNum, UInt dc); #if ADAPTIVE_QP_SELECTION Void initSliceQpDelta() ; Void storeSliceQpNext(TComSlice* pcSlice); Void clearSliceARLCnt(); Int getQpDelta(Int qp) { return m_qpDelta[qp]; } Int* getSliceNSamples(){ return m_sliceNsamples ;} Double* getSliceSumC() { return m_sliceSumC; } #endif Void transformSkipQuantOneSample(TComTU &rTu, const ComponentID compID, const TCoeff resiDiff, TCoeff* pcCoeff, const UInt uiPos, const QpParam &cQP, const Bool bUseHalfRoundingPoint); Void invTrSkipDeQuantOneSample(TComTU &rTu, ComponentID compID, TCoeff pcCoeff, Pel &reconSample, const QpParam &cQP, UInt uiPos ); protected: #if ADAPTIVE_QP_SELECTION Int m_qpDelta[MAX_QP+1]; Int m_sliceNsamples[LEVEL_RANGE+1]; Double m_sliceSumC[LEVEL_RANGE+1] ; #endif TCoeff* m_plTempCoeff; // QpParam m_cQP; - removed - placed on the stack. #if RDOQ_CHROMA_LAMBDA Double m_lambdas[MAX_NUM_COMPONENT]; #endif Double m_dLambda; UInt m_uiRDOQOffset; UInt m_uiMaxTrSize; Bool m_bEnc; Bool m_useRDOQ; Bool m_useRDOQTS; Bool m_useSelectiveRDOQ; #if ADAPTIVE_QP_SELECTION Bool m_bUseAdaptQpSelect; #endif Bool m_useTransformSkipFast; Bool m_scalingListEnabledFlag; Int *m_quantCoef [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; ///< array of quantization matrix coefficient 4x4 Int *m_dequantCoef [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; ///< array of dequantization matrix coefficient 4x4 Double *m_errScale [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; ///< array of quantization matrix coefficient 4x4 Double m_errScaleNoScalingList[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; ///< array of quantization matrix coefficient 4x4 private: // forward Transform Void xT ( const Int channelBitDepth, Bool useDST, Pel* piBlkResi, UInt uiStride, TCoeff* psCoeff, Int iWidth, Int iHeight, const Int maxLog2TrDynamicRange ); // skipping Transform Void xTransformSkip ( Pel* piBlkResi, UInt uiStride, TCoeff* psCoeff, TComTU &rTu, const ComponentID component ); Void signBitHidingHDQ( TCoeff* pQCoef, TCoeff* pCoef, TCoeff* deltaU, const TUEntropyCodingParameters &codingParameters, const Int maxLog2TrDynamicRange ); // quantization Void xQuant( TComTU &rTu, TCoeff * pSrc, TCoeff * pDes, #if ADAPTIVE_QP_SELECTION TCoeff *pArlDes, #endif TCoeff &uiAbsSum, const ComponentID compID, const QpParam &cQP ); Bool xNeedRDOQ( TComTU &rTu, TCoeff * pSrc, const ComponentID compID, const QpParam &cQP ); // RDOQ functions Void xRateDistOptQuant ( TComTU &rTu, TCoeff * plSrcCoeff, TCoeff * piDstCoeff, #if ADAPTIVE_QP_SELECTION TCoeff *piArlDstCoeff, #endif TCoeff &uiAbsSum, const ComponentID compID, const QpParam &cQP ); __inline UInt xGetCodedLevel ( Double& rd64CodedCost, Double& rd64CodedCost0, Double& rd64CodedCostSig, Intermediate_Int lLevelDouble, UInt uiMaxAbsLevel, UShort ui16CtxNumSig, UShort ui16CtxNumOne, UShort ui16CtxNumAbs, UShort ui16AbsGoRice, UInt c1Idx, UInt c2Idx, Int iQBits, Double errorScale, Bool bLast, Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ) const; __inline Int xGetICRate ( const UInt uiAbsLevel, const UShort ui16CtxNumOne, const UShort ui16CtxNumAbs, const UShort ui16AbsGoRice, const UInt c1Idx, const UInt c2Idx, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ) const; __inline Double xGetRateLast ( const UInt uiPosX, const UInt uiPosY, const ComponentID component ) const; __inline Double xGetRateSigCoeffGroup( UShort uiSignificanceCoeffGroup, UShort ui16CtxNumSig ) const; __inline Double xGetRateSigCoef ( UShort uiSignificance, UShort ui16CtxNumSig ) const; __inline Double xGetICost ( Double dRate ) const; __inline Double xGetIEPRate ( ) const; // dequantization Void xDeQuant( TComTU &rTu, const TCoeff * pSrc, TCoeff * pDes, const ComponentID compID, const QpParam &cQP ); // inverse transform Void xIT ( const Int channelBitDepth, Bool useDST, TCoeff* plCoef, Pel* pResidual, UInt uiStride, Int iWidth, Int iHeight, const Int maxLog2TrDynamicRange ); // inverse skipping transform Void xITransformSkip ( TCoeff* plCoef, Pel* pResidual, UInt uiStride, TComTU &rTu, const ComponentID component ); public: static Void crossComponentPrediction( TComTU &rTu, const ComponentID compID, const Pel *piResiL, const Pel *piResiC, Pel *piResiT, const Int width, const Int height, const Int strideL, const Int strideC, const Int strideT, const Bool reverse); };// END CLASS DEFINITION TComTrQuant //! \} #endif // __TCOMTRQUANT__ HM-HM-18.0/source/Lib/TLibCommon/TComWeightPrediction.cpp000066400000000000000000000365331442026013100230230ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComWeightPrediction.h \brief weighting prediction class (header) */ // Include files #include "CommonDef.h" #include "TComYuv.h" #include "TComPic.h" #include "TComInterpolationFilter.h" #include "TComWeightPrediction.h" static inline Pel weightBidir( Int w0, Pel P0, Int w1, Pel P1, Int round, Int shift, Int offset, Int clipBD) { return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + w1*(P1 + IF_INTERNAL_OFFS) + round + (offset << (shift-1))) >> shift ), clipBD ); } static inline Pel weightUnidir( Int w0, Pel P0, Int round, Int shift, Int offset, Int clipBD) { return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + round) >> shift ) + offset, clipBD ); } static inline Pel noWeightUnidir( Pel P0, Int round, Int shift, Int offset, Int clipBD) { return ClipBD( ( ((P0 + IF_INTERNAL_OFFS) + round) >> shift ) + offset, clipBD ); } static inline Pel noWeightOffsetUnidir( Pel P0, Int round, Int shift, Int clipBD) { return ClipBD( ( ((P0 + IF_INTERNAL_OFFS) + round) >> shift ), clipBD ); } // ==================================================================================================================== // Class definition // ==================================================================================================================== TComWeightPrediction::TComWeightPrediction() { } //! weighted averaging for bi-pred Void TComWeightPrediction::addWeightBi( const TComYuv *pcYuvSrc0, const TComYuv *pcYuvSrc1, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, const WPScalingParam *const wp1, TComYuv *const rpcYuvDst, const Bool bRoundLuma) { const Bool enableRounding[MAX_NUM_COMPONENT]={ bRoundLuma, true, true }; const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents(); for(Int componentIndex=0; componentIndexgetAddr( compID, iPartUnitIdx ); const Pel* pSrc1 = pcYuvSrc1->getAddr( compID, iPartUnitIdx ); Pel* pDst = rpcYuvDst->getAddr( compID, iPartUnitIdx ); // Luma : -------------------------------------------- const Int w0 = wp0[compID].w; const Int offset = wp0[compID].offset; const Int clipBD = bitDepths.recon[toChannelType(compID)]; const Int shiftNum = std::max(2, (IF_INTERNAL_PREC - clipBD)); const Int shift = wp0[compID].shift + shiftNum; const Int round = (enableRounding[compID] && (shift > 0)) ? (1<<(shift-1)) : 0; const Int w1 = wp1[compID].w; const UInt csx = pcYuvSrc0->getComponentScaleX(compID); const UInt csy = pcYuvSrc0->getComponentScaleY(compID); const Int iHeight = uiHeight>>csy; const Int iWidth = uiWidth>>csx; const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iSrc1Stride = pcYuvSrc1->getStride(compID); const UInt iDstStride = rpcYuvDst->getStride(compID); for ( Int y = iHeight-1; y >= 0; y-- ) { // do it in batches of 4 (partial unroll) Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--; } for( ; x >= 0; x-- ) { pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } // y loop } // compID loop } //! weighted averaging for uni-pred Void TComWeightPrediction::addWeightUni( const TComYuv *const pcYuvSrc0, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, TComYuv *const pcYuvDst ) { const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents(); for(Int componentIndex=0; componentIndexgetAddr( compID, iPartUnitIdx ); Pel* pDst = pcYuvDst->getAddr( compID, iPartUnitIdx ); // Luma : -------------------------------------------- const Int w0 = wp0[compID].w; const Int offset = wp0[compID].offset; const Int clipBD = bitDepths.recon[toChannelType(compID)]; const Int shiftNum = std::max(2, (IF_INTERNAL_PREC - clipBD)); const Int shift = wp0[compID].shift + shiftNum; const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); const UInt csx = pcYuvSrc0->getComponentScaleX(compID); const UInt csy = pcYuvSrc0->getComponentScaleY(compID); const Int iHeight = uiHeight>>csy; const Int iWidth = uiWidth>>csx; if (w0 != 1 << wp0[compID].shift) { const Int round = (shift > 0) ? (1<<(shift-1)) : 0; for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } else { const Int round = (shiftNum > 0) ? (1<<(shiftNum-1)) : 0; if (offset == 0) { for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } else { for (Int y = iHeight-1; y >= 0; y-- ) { Int x = iWidth-1; for ( ; x >= 3; ) { pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--; } for( ; x >= 0; x--) { pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); } pSrc0 += iSrc0Stride; pDst += iDstStride; } } } } } //======================================================= // getWpScaling() //======================================================= //! derivation of wp tables Void TComWeightPrediction::getWpScaling( TComDataCU *const pcCU, const Int iRefIdx0, const Int iRefIdx1, WPScalingParam *&wp0, WPScalingParam *&wp1) { assert(iRefIdx0 >= 0 || iRefIdx1 >= 0); TComSlice *const pcSlice = pcCU->getSlice(); const Bool wpBiPred = pcCU->getSlice()->getPPS()->getWPBiPred(); const Bool bBiPred = (iRefIdx0>=0 && iRefIdx1>=0); const Bool bUniPred = !bBiPred; if ( bUniPred || wpBiPred ) { // explicit -------------------- if ( iRefIdx0 >= 0 ) { pcSlice->getWpScaling(REF_PIC_LIST_0, iRefIdx0, wp0); } if ( iRefIdx1 >= 0 ) { pcSlice->getWpScaling(REF_PIC_LIST_1, iRefIdx1, wp1); } } else { assert(0); } if ( iRefIdx0 < 0 ) { wp0 = NULL; } if ( iRefIdx1 < 0 ) { wp1 = NULL; } const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents(); const Bool bUseHighPrecisionPredictionWeighting = pcSlice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); if ( bBiPred ) { // Bi-predictive case for ( Int yuv=0 ; yuvgetSPS()->getBitDepth(toChannelType(ComponentID(yuv))); const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8)); wp0[yuv].w = wp0[yuv].iWeight; wp1[yuv].w = wp1[yuv].iWeight; wp0[yuv].o = wp0[yuv].iOffset * offsetScalingFactor; wp1[yuv].o = wp1[yuv].iOffset * offsetScalingFactor; wp0[yuv].offset = wp0[yuv].o + wp1[yuv].o; wp0[yuv].shift = wp0[yuv].uiLog2WeightDenom + 1; wp0[yuv].round = (1 << wp0[yuv].uiLog2WeightDenom); wp1[yuv].offset = wp0[yuv].offset; wp1[yuv].shift = wp0[yuv].shift; wp1[yuv].round = wp0[yuv].round; } } else { // UniPred WPScalingParam *const pwp = (iRefIdx0>=0) ? wp0 : wp1 ; for ( Int yuv=0 ; yuvgetSPS()->getBitDepth(toChannelType(ComponentID(yuv))); const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8)); pwp[yuv].w = pwp[yuv].iWeight; pwp[yuv].offset = pwp[yuv].iOffset * offsetScalingFactor; pwp[yuv].shift = pwp[yuv].uiLog2WeightDenom; pwp[yuv].round = (pwp[yuv].uiLog2WeightDenom>=1) ? (1 << (pwp[yuv].uiLog2WeightDenom-1)) : (0); } } } //! weighted prediction for bi-pred Void TComWeightPrediction::xWeightedPredictionBi( TComDataCU *const pcCU, const TComYuv *const pcYuvSrc0, const TComYuv *const pcYuvSrc1, const Int iRefIdx0, const Int iRefIdx1, const UInt uiPartIdx, const Int iWidth, const Int iHeight, TComYuv *rpcYuvDst ) { WPScalingParam *pwp0; WPScalingParam *pwp1; assert(pcCU->getSlice()->getPPS()->getWPBiPred()); getWpScaling(pcCU, iRefIdx0, iRefIdx1, pwp0, pwp1); if( iRefIdx0 >= 0 && iRefIdx1 >= 0 ) { addWeightBi(pcYuvSrc0, pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, pwp1, rpcYuvDst ); } else if ( iRefIdx0 >= 0 && iRefIdx1 < 0 ) { addWeightUni( pcYuvSrc0, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, rpcYuvDst ); } else if ( iRefIdx0 < 0 && iRefIdx1 >= 0 ) { addWeightUni( pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp1, rpcYuvDst ); } else { assert (0); } } //! weighted prediction for uni-pred Void TComWeightPrediction::xWeightedPredictionUni( TComDataCU *const pcCU, const TComYuv *const pcYuvSrc, const UInt uiPartAddr, const Int iWidth, const Int iHeight, const RefPicList eRefPicList, TComYuv *pcYuvPred, const Int iRefIdx_input) { WPScalingParam *pwp, *pwpTmp; Int iRefIdx=iRefIdx_input; if ( iRefIdx < 0 ) { iRefIdx = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr ); } assert (iRefIdx >= 0); if ( eRefPicList == REF_PIC_LIST_0 ) { getWpScaling(pcCU, iRefIdx, -1, pwp, pwpTmp); } else { getWpScaling(pcCU, -1, iRefIdx, pwpTmp, pwp); } addWeightUni( pcYuvSrc, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartAddr, iWidth, iHeight, pwp, pcYuvPred ); } HM-HM-18.0/source/Lib/TLibCommon/TComWeightPrediction.h000066400000000000000000000121141442026013100224550ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComWeightPrediction.h \brief weighting prediction class (header) */ #ifndef __TCOMWEIGHTPREDICTION__ #define __TCOMWEIGHTPREDICTION__ #include "CommonDef.h" // forward declarations class TComDataCU; class TComYuv; struct WPScalingParam; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// weighting prediction class class TComWeightPrediction { public: TComWeightPrediction(); Void getWpScaling( TComDataCU *const pcCU, const Int iRefIdx0, const Int iRefIdx1, WPScalingParam *&wp0, WPScalingParam *&wp1); Void addWeightBi( const TComYuv *pcYuvSrc0, const TComYuv *pcYuvSrc1, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, const WPScalingParam *const wp1, TComYuv *const rpcYuvDst, const Bool bRoundLuma=true ); Void addWeightUni( const TComYuv *const pcYuvSrc0, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, TComYuv *const rpcYuvDst ); Void xWeightedPredictionUni( TComDataCU *const pcCU, const TComYuv *const pcYuvSrc, const UInt uiPartAddr, const Int iWidth, const Int iHeight, const RefPicList eRefPicList, TComYuv *pcYuvPred, const Int iRefIdx=-1 ); Void xWeightedPredictionBi( TComDataCU *const pcCU, const TComYuv *const pcYuvSrc0, const TComYuv *const pcYuvSrc1, const Int iRefIdx0, const Int iRefIdx1, const UInt uiPartIdx, const Int iWidth, const Int iHeight, TComYuv *pcYuvDst ); }; #endif HM-HM-18.0/source/Lib/TLibCommon/TComYuv.cpp000066400000000000000000000343021442026013100203260ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComYuv.cpp \brief general YUV buffer class \todo this should be merged with TComPicYuv */ #include #include #include #include #include "CommonDef.h" #include "TComYuv.h" #include "TComInterpolationFilter.h" //! \ingroup TLibCommon //! \{ TComYuv::TComYuv() { for(Int comp=0; comp>uiPartDepth; const Int iHeight = getHeight(compID)>>uiPartDepth; const Pel* pSrc = getAddr(compID, uiPartIdx, iWidth); Pel* pDst = pcPicYuvDst->getAddr ( compID, ctuRsAddr, uiAbsZorderIdx ); const UInt iSrcStride = getStride(compID); const UInt iDstStride = pcPicYuvDst->getStride(compID); for ( Int y = iHeight; y != 0; y-- ) { ::memcpy( pDst, pSrc, sizeof(Pel)*iWidth); pDst += iDstStride; pSrc += iSrcStride; } } Void TComYuv::copyFromPicYuv ( const TComPicYuv* pcPicYuvSrc, const UInt ctuRsAddr, const UInt uiAbsZorderIdx ) { for(Int comp=0; compgetAddr ( compID, ctuRsAddr, uiAbsZorderIdx ); const UInt iDstStride = getStride(compID); const UInt iSrcStride = pcPicYuvSrc->getStride(compID); const Int iWidth=getWidth(compID); const Int iHeight=getHeight(compID); for (Int y = iHeight; y != 0; y-- ) { ::memcpy( pDst, pSrc, sizeof(Pel)*iWidth); pDst += iDstStride; pSrc += iSrcStride; } } Void TComYuv::copyToPartYuv( TComYuv* pcYuvDst, const UInt uiDstPartIdx ) const { for(Int comp=0; compgetAddr( compID, uiDstPartIdx ); const UInt iSrcStride = getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); const Int iWidth=getWidth(compID); const Int iHeight=getHeight(compID); for (Int y = iHeight; y != 0; y-- ) { ::memcpy( pDst, pSrc, sizeof(Pel)*iWidth); pDst += iDstStride; pSrc += iSrcStride; } } Void TComYuv::copyPartToYuv( TComYuv* pcYuvDst, const UInt uiSrcPartIdx ) const { for(Int comp=0; compgetAddr(compID, 0 ); const UInt iSrcStride = getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); const UInt uiHeight = pcYuvDst->getHeight(compID); const UInt uiWidth = pcYuvDst->getWidth(compID); for ( UInt y = uiHeight; y != 0; y-- ) { ::memcpy( pDst, pSrc, sizeof(Pel)*uiWidth); pDst += iDstStride; pSrc += iSrcStride; } } Void TComYuv::copyPartToPartYuv ( TComYuv* pcYuvDst, const UInt uiPartIdx, const UInt iWidth, const UInt iHeight ) const { for(Int comp=0; comp>getComponentScaleX(ComponentID(comp)), iHeight>>getComponentScaleY(ComponentID(comp)) ); } } Void TComYuv::copyPartToPartComponent ( const ComponentID compID, TComYuv* pcYuvDst, const UInt uiPartIdx, const UInt iWidthComponent, const UInt iHeightComponent ) const { const Pel* pSrc = getAddr(compID, uiPartIdx); Pel* pDst = pcYuvDst->getAddr(compID, uiPartIdx); if( pSrc == pDst ) { //th not a good idea //th best would be to fix the caller return ; } const UInt iSrcStride = getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); for ( UInt y = iHeightComponent; y != 0; y-- ) { ::memcpy( pDst, pSrc, iWidthComponent * sizeof(Pel) ); pSrc += iSrcStride; pDst += iDstStride; } } Void TComYuv::copyPartToPartComponentMxN ( const ComponentID compID, TComYuv* pcYuvDst, const TComRectangle &rect) const { const Pel* pSrc = getAddrPix( compID, rect.x0, rect.y0 ); Pel* pDst = pcYuvDst->getAddrPix( compID, rect.x0, rect.y0 ); if( pSrc == pDst ) { //th not a good idea //th best would be to fix the caller return ; } const UInt iSrcStride = getStride(compID); const UInt iDstStride = pcYuvDst->getStride(compID); const UInt uiHeightComponent=rect.height; const UInt uiWidthComponent=rect.width; for ( UInt y = uiHeightComponent; y != 0; y-- ) { ::memcpy( pDst, pSrc, uiWidthComponent * sizeof( Pel ) ); pSrc += iSrcStride; pDst += iDstStride; } } Void TComYuv::addClip( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt uiTrUnitIdx, const UInt uiPartSize, const BitDepths &clipBitDepths ) { for(Int comp=0; comp>getComponentScaleX(compID); const Int uiPartHeight=uiPartSize>>getComponentScaleY(compID); const Pel* pSrc0 = pcYuvSrc0->getAddr(compID, uiTrUnitIdx, uiPartWidth ); const Pel* pSrc1 = pcYuvSrc1->getAddr(compID, uiTrUnitIdx, uiPartWidth ); Pel* pDst = getAddr(compID, uiTrUnitIdx, uiPartWidth ); const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iSrc1Stride = pcYuvSrc1->getStride(compID); const UInt iDstStride = getStride(compID); const Int clipbd = clipBitDepths.recon[toChannelType(compID)]; #if O0043_BEST_EFFORT_DECODING const Int bitDepthDelta = clipBitDepths.stream[toChannelType(compID)] - clipbd; #endif for ( Int y = uiPartHeight-1; y >= 0; y-- ) { for ( Int x = uiPartWidth-1; x >= 0; x-- ) { #if O0043_BEST_EFFORT_DECODING pDst[x] = Pel(ClipBD( Int(pSrc0[x]) + rightShiftEvenRounding(pSrc1[x], bitDepthDelta), clipbd)); #else pDst[x] = Pel(ClipBD( Int(pSrc0[x]) + Int(pSrc1[x]), clipbd)); #endif } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } } } Void TComYuv::subtract( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt uiTrUnitIdx, const UInt uiPartSize ) { for(Int comp=0; comp>getComponentScaleX(compID); const Int uiPartHeight=uiPartSize>>getComponentScaleY(compID); const Pel* pSrc0 = pcYuvSrc0->getAddr( compID, uiTrUnitIdx, uiPartWidth ); const Pel* pSrc1 = pcYuvSrc1->getAddr( compID, uiTrUnitIdx, uiPartWidth ); Pel* pDst = getAddr( compID, uiTrUnitIdx, uiPartWidth ); const Int iSrc0Stride = pcYuvSrc0->getStride(compID); const Int iSrc1Stride = pcYuvSrc1->getStride(compID); const Int iDstStride = getStride(compID); for (Int y = uiPartHeight-1; y >= 0; y-- ) { for (Int x = uiPartWidth-1; x >= 0; x-- ) { pDst[x] = pSrc0[x] - pSrc1[x]; } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } } } Void TComYuv::addAvg( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const BitDepths &clipBitDepths ) { for(Int comp=0; compgetAddr( compID, iPartUnitIdx ); const Pel* pSrc1 = pcYuvSrc1->getAddr( compID, iPartUnitIdx ); Pel* pDst = getAddr( compID, iPartUnitIdx ); const UInt iSrc0Stride = pcYuvSrc0->getStride(compID); const UInt iSrc1Stride = pcYuvSrc1->getStride(compID); const UInt iDstStride = getStride(compID); const Int clipbd = clipBitDepths.recon[toChannelType(compID)]; const Int shiftNum = std::max(2, (IF_INTERNAL_PREC - clipbd)) + 1; const Int offset = ( 1 << ( shiftNum - 1 ) ) + 2 * IF_INTERNAL_OFFS; const Int iWidth = uiWidth >> getComponentScaleX(compID); const Int iHeight = uiHeight >> getComponentScaleY(compID); if (iWidth&1) { assert(0); exit(-1); } else if (iWidth&2) { for ( Int y = 0; y < iHeight; y++ ) { for (Int x=0 ; x < iWidth; x+=2 ) { pDst[ x + 0 ] = ClipBD( rightShift(( pSrc0[ x + 0 ] + pSrc1[ x + 0 ] + offset ), shiftNum), clipbd ); pDst[ x + 1 ] = ClipBD( rightShift(( pSrc0[ x + 1 ] + pSrc1[ x + 1 ] + offset ), shiftNum), clipbd ); } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } } else { for ( Int y = 0; y < iHeight; y++ ) { for (Int x=0 ; x < iWidth; x+=4 ) { pDst[ x + 0 ] = ClipBD( rightShift(( pSrc0[ x + 0 ] + pSrc1[ x + 0 ] + offset ), shiftNum), clipbd ); pDst[ x + 1 ] = ClipBD( rightShift(( pSrc0[ x + 1 ] + pSrc1[ x + 1 ] + offset ), shiftNum), clipbd ); pDst[ x + 2 ] = ClipBD( rightShift(( pSrc0[ x + 2 ] + pSrc1[ x + 2 ] + offset ), shiftNum), clipbd ); pDst[ x + 3 ] = ClipBD( rightShift(( pSrc0[ x + 3 ] + pSrc1[ x + 3 ] + offset ), shiftNum), clipbd ); } pSrc0 += iSrc0Stride; pSrc1 += iSrc1Stride; pDst += iDstStride; } } } } Void TComYuv::removeHighFreq( const TComYuv* pcYuvSrc, const UInt uiPartIdx, const UInt uiWidth, const UInt uiHeight, const Int bitDepths[MAX_NUM_CHANNEL_TYPE], const Bool bClipToBitDepths ) { for(Int comp=0; compgetAddr(compID, uiPartIdx); Pel* pDst = getAddr(compID, uiPartIdx); const Int iSrcStride = pcYuvSrc->getStride(compID); const Int iDstStride = getStride(compID); const Int iWidth = uiWidth >>getComponentScaleX(compID); const Int iHeight = uiHeight>>getComponentScaleY(compID); if (bClipToBitDepths) { const Int clipBd=bitDepths[toChannelType(compID)]; for ( Int y = iHeight-1; y >= 0; y-- ) { for ( Int x = iWidth-1; x >= 0; x-- ) { pDst[x ] = ClipBD((2 * pDst[x]) - pSrc[x], clipBd); } pSrc += iSrcStride; pDst += iDstStride; } } else { for ( Int y = iHeight-1; y >= 0; y-- ) { for ( Int x = iWidth-1; x >= 0; x-- ) { pDst[x ] = (2 * pDst[x]) - pSrc[x]; } pSrc += iSrcStride; pDst += iDstStride; } } } } //! \} HM-HM-18.0/source/Lib/TLibCommon/TComYuv.h000066400000000000000000000313421442026013100177740ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TComYuv.h \brief general YUV buffer class (header) \todo this should be merged with TComPicYuv \n check usage of removeHighFreq function */ #ifndef __TCOMYUV__ #define __TCOMYUV__ #include "CommonDef.h" #include "TComPicYuv.h" #include "TComRectangle.h" //! \ingroup TLibCommon //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// general YUV buffer class class TComYuv { private: // ------------------------------------------------------------------------------------------------------------------ // YUV buffer // ------------------------------------------------------------------------------------------------------------------ Pel* m_apiBuf[MAX_NUM_COMPONENT]; // ------------------------------------------------------------------------------------------------------------------ // Parameter for general YUV buffer usage // ------------------------------------------------------------------------------------------------------------------ UInt m_iWidth; UInt m_iHeight; ChromaFormat m_chromaFormatIDC; ////< Chroma Format // dims 16x16 // blkSize=4x4 // these functions assume a square CU, of size width*width, split into square TUs each of size blkSize*blkSize. // iTransUnitIdx is the raster-scanned index of the sub-block (TU) in question. // eg for a 16x16 CU, with 4x4 TUs: // 0 1 2 3 // 4 5 6 7 // 8 9 10 11 // 12 13 14 15 // So, for iTransUnitIdx=14, 14*4 & 15 =8=X offset. // 14*4 / 16 =3=Y block offset // 3*4*16 = Y offset within buffer public: TComYuv (); virtual ~TComYuv (); // ------------------------------------------------------------------------------------------------------------------ // Memory management // ------------------------------------------------------------------------------------------------------------------ Void create ( const UInt iWidth, const UInt iHeight, const ChromaFormat chromaFormatIDC ); ///< Create YUV buffer Void destroy (); ///< Destroy YUV buffer Void clear (); ///< clear YUV buffer // ------------------------------------------------------------------------------------------------------------------ // Copy, load, store YUV buffer // ------------------------------------------------------------------------------------------------------------------ // Copy YUV buffer to picture buffer Void copyToPicYuv ( TComPicYuv* pcPicYuvDst, const UInt ctuRsAddr, const UInt uiAbsZorderIdx, const UInt uiPartDepth = 0, const UInt uiPartIdx = 0 ) const ; Void copyToPicComponent ( const ComponentID id, TComPicYuv* pcPicYuvDst, const UInt iCtuRsAddr, const UInt uiAbsZorderIdx, const UInt uiPartDepth = 0, const UInt uiPartIdx = 0 ) const ; // Copy YUV buffer from picture buffer Void copyFromPicYuv ( const TComPicYuv* pcPicYuvSrc, const UInt ctuRsAddr, const UInt uiAbsZorderIdx ); Void copyFromPicComponent ( const ComponentID id, const TComPicYuv* pcPicYuvSrc, const UInt iCtuRsAddr, const UInt uiAbsZorderIdx ); // Copy Small YUV buffer to the part of other Big YUV buffer Void copyToPartYuv ( TComYuv* pcYuvDst, const UInt uiDstPartIdx ) const ; Void copyToPartComponent ( const ComponentID id, TComYuv* pcYuvDst, const UInt uiDstPartIdx ) const ; // Copy the part of Big YUV buffer to other Small YUV buffer Void copyPartToYuv ( TComYuv* pcYuvDst, const UInt uiSrcPartIdx ) const; Void copyPartToComponent ( const ComponentID id, TComYuv* pcYuvDst, const UInt uiSrcPartIdx ) const; // Copy YUV partition buffer to other YUV partition buffer Void copyPartToPartYuv ( TComYuv* pcYuvDst, const UInt uiPartIdx, const UInt uiWidth, const UInt uiHeight ) const; Void copyPartToPartComponent ( const ComponentID id, TComYuv* pcYuvDst, const UInt uiPartIdx, const UInt uiWidthComponent, const UInt uiHeightComponent ) const; // Copy YUV partition buffer to other YUV partition buffer for non-square blocks Void copyPartToPartComponentMxN ( const ComponentID id, TComYuv* pcYuvDst, const TComRectangle &rect ) const; // ------------------------------------------------------------------------------------------------------------------ // Algebraic operation for YUV buffer // ------------------------------------------------------------------------------------------------------------------ // Clip(pcYuvSrc0 + pcYuvSrc1) -> m_apiBuf Void addClip ( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt uiTrUnitIdx, const UInt uiPartSize, const BitDepths &clipBitDepths ); // pcYuvSrc0 - pcYuvSrc1 -> m_apiBuf Void subtract ( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt uiTrUnitIdx, const UInt uiPartSize ); // (pcYuvSrc0 + pcYuvSrc1)/2 for YUV partition Void addAvg ( const TComYuv* pcYuvSrc0, const TComYuv* pcYuvSrc1, const UInt iPartUnitIdx, const UInt iWidth, const UInt iHeight, const BitDepths &clipBitDepths ); Void removeHighFreq ( const TComYuv* pcYuvSrc, const UInt uiPartIdx, const UInt uiWidth, const UInt uiHeight , const Int bitDepths[MAX_NUM_CHANNEL_TYPE], const Bool bClipToBitDepths ); // ------------------------------------------------------------------------------------------------------------------ // Access function for YUV buffer // ------------------------------------------------------------------------------------------------------------------ // Access starting position of YUV buffer Pel* getAddr (const ComponentID id) { return m_apiBuf[id]; } const Pel* getAddr (const ComponentID id) const { return m_apiBuf[id]; } // Access starting position of YUV partition unit buffer Pel* getAddr (const ComponentID id, const UInt uiPartUnitIdx) { Int blkX = g_auiRasterToPelX[ g_auiZscanToRaster[ uiPartUnitIdx ] ] >> getComponentScaleX(id); Int blkY = g_auiRasterToPelY[ g_auiZscanToRaster[ uiPartUnitIdx ] ] >> getComponentScaleY(id); assert((blkX> getComponentScaleX(id); Int blkY = g_auiRasterToPelY[ g_auiZscanToRaster[ uiPartUnitIdx ] ] >> getComponentScaleY(id); assert((blkX> getComponentScaleX(id); } UInt getHeight (const ComponentID id) const { return m_iHeight >> getComponentScaleY(id); } UInt getWidth (const ComponentID id) const { return m_iWidth >> getComponentScaleX(id); } ChromaFormat getChromaFormat () const { return m_chromaFormatIDC; } UInt getNumberValidComponents () const { return ::getNumberValidComponents(m_chromaFormatIDC); } UInt getComponentScaleX (const ComponentID id) const { return ::getComponentScaleX(id, m_chromaFormatIDC); } UInt getComponentScaleY (const ComponentID id) const { return ::getComponentScaleY(id, m_chromaFormatIDC); } };// END CLASS DEFINITION TComYuv //! \} #endif // __TCOMYUV__ HM-HM-18.0/source/Lib/TLibCommon/TypeDef.h000066400000000000000000001113171442026013100177670ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TypeDef.h \brief Define macros, basic types, new types and enumerations */ #ifndef __TYPEDEF__ #define __TYPEDEF__ #ifndef __COMMONDEF__ #error Include CommonDef.h not TypeDef.h #endif #include #include #include //! \ingroup TLibCommon //! \{ #define JCTVC_AD0021_SEI_MANIFEST 1 // JCTVC_AD0021(JVET-T0056): SEI manifest SEI message #define JCTVC_AD0021_SEI_PREFIX_INDICATION 1 // JCTVC_AD0021(JVET-T0056): SEI prefix indication SEI message #define JVET_X0079_MODIFIED_BITRATES 1 // JVET-X0079: Addition of level 6.3 #define JVET_V0078 1 // JVET-V0078: QP control for very smooth blocks #define JVET_Y0077_BIM 1 // JVET-Y0077: Block Importance Mapping #define JVET_Y0105_SW_AND_QDF 1 // An adaptive smooth window (SW) size and extension of quality dependency factor (QDF) to low frame rate in rate control // ==================================================================================================================== // Debugging // ==================================================================================================================== #define DEBUG_STRING 0 ///< When enabled, prints out final decision debug info at encoder and decoder #define DEBUG_ENCODER_SEARCH_BINS 0 ///< When enabled, prints out each bin as it is coded during encoder search #define DEBUG_CABAC_BINS 0 ///< When enabled, prints out each bin as it is coded during final encode and decode #define DEBUG_INTRA_SEARCH_COSTS 0 ///< When enabled, prints out the cost for each mode during encoder search #define DEBUG_TRANSFORM_AND_QUANTISE 0 ///< When enabled, prints out each TU as it passes through the transform-quantise-dequantise-inverseTransform process #define ENVIRONMENT_VARIABLE_DEBUG_AND_TEST 0 ///< When enabled, allows control of debug modifications via environment variables #define PRINT_MACRO_VALUES 1 ///< When enabled, the encoder prints out a list of the non-environment-variable controlled macros and their values on startup // TODO: rename this macro to DECODER_DEBUG_BIT_STATISTICS (may currently cause merge issues with other branches) // This can be enabled by the makefile #ifndef RExt__DECODER_DEBUG_BIT_STATISTICS #define RExt__DECODER_DEBUG_BIT_STATISTICS 0 ///< 0 (default) = decoder reports as normal, 1 = decoder produces bit usage statistics (will impact decoder run time by up to ~10%) #endif // This can be enabled by the makefile #ifndef ENC_DEC_TRACE #define ENC_DEC_TRACE 0 #endif #define DEC_NUH_TRACE 0 ///< When trace enabled, enable tracing of NAL unit headers at the decoder (currently not possible at the encoder) #define PRINT_RPS_INFO 0 ///< Enable/disable the printing of bits used to send the RPS. #define MCTS_EXTRACTION 1 ///< Additional project for MCTS Extraction as in JCTVC-AC1005 // ==================================================================================================================== // Tool Switches - transitory (these macros are likely to be removed in future revisions) // ==================================================================================================================== #define JVET_V0056_MCTF 1 // JVET-V0056: Changes to MCTF #define JVET_K0390_RATE_CTRL 1 #if JVET_K0390_RATE_CTRL #define JVET_M0600_RATE_CTRL 1 #endif #define DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES 1 ///< TODO: integrate this macro into a broader conformance checking system. #define MCTS_ENC_CHECK 1 ///< Temporal MCTS encoder constraint and decoder checks. Also requires SEITMCTSTileConstraint to be enabled to enforce constraint #define SHUTTER_INTERVAL_SEI_MESSAGE 1 ///< support for shutter interval SEI message #define SEI_ENCODER_CONTROL 1 ///< add encoder control for the following SEI: film grain characteristics, content light level, ambient viewing environment #define DPB_ENCODER_USAGE_CHECK 1 ///< Adds DPB encoder usage check. #define JVET_X0048_X0103_FILM_GRAIN 1 ///< JVET-X0048-X0103: SMPTE RDD-5 based film grain analysis and synthesis model for film grain characterstics (FGC) SEI #define JVET_T0050_ANNOTATED_REGIONS_SEI 1 ///< Detect static objects and use it in Annotated Regions SEI message #if SHUTTER_INTERVAL_SEI_MESSAGE #define SHUTTER_INTERVAL_SEI_PROCESSING 1 ///< JCTVC-AM0024: pre-/post-processing to use shutter interval SEI #endif // ==================================================================================================================== // Tool Switches // ==================================================================================================================== // Please also refer to "TDecConformance.h" for DECODER_PARTIAL_CONFORMANCE_CHECK #ifndef EXTENSION_360_VIDEO #define EXTENSION_360_VIDEO 0 ///< extension for 360/spherical video coding support; this macro should be controlled by makefile, as it would be used to control whether the library is built and linked #endif #define REDUCED_ENCODER_MEMORY 1 ///< When 1, the encoder will allocate TComPic memory when required and release it when no longer required. #define ADAPTIVE_QP_SELECTION 1 ///< G382: Adaptive reconstruction levels, non-normative part for adaptive QP selection #define AMP_ENC_SPEEDUP 1 ///< encoder only speed-up by AMP mode skipping #if AMP_ENC_SPEEDUP #define AMP_MRG 1 ///< encoder only force merge for AMP partition (no motion search for AMP) #endif #define FAST_BIT_EST 1 ///< G763: Table-based bit estimation for CABAC #define HHI_RQT_INTRA_SPEEDUP 1 ///< tests one best mode with full rqt #define HHI_RQT_INTRA_SPEEDUP_MOD 0 ///< tests two best modes with full rqt #if HHI_RQT_INTRA_SPEEDUP_MOD && !HHI_RQT_INTRA_SPEEDUP #error #endif #define MATRIX_MULT 0 ///< Brute force matrix multiplication instead of partial butterfly #define O0043_BEST_EFFORT_DECODING 0 ///< 0 (default) = disable code related to best effort decoding, 1 = enable code relating to best effort decoding [ decode-side only ]. #define ME_ENABLE_ROUNDING_OF_MVS 1 ///< 0 (default) = disables rounding of motion vectors when right shifted, 1 = enables rounding #define RDOQ_CHROMA_LAMBDA 1 ///< F386: weighting of chroma for RDOQ // This can be enabled by the makefile #ifndef RExt__HIGH_BIT_DEPTH_SUPPORT #define RExt__HIGH_BIT_DEPTH_SUPPORT 0 ///< 0 (default) use data type definitions for 8-10 bit video, 1 = use larger data types to allow for up to 16-bit video (originally developed as part of N0188) #endif #if defined __SSE2__ || defined __AVX2__ || defined __AVX__ || defined _M_AMD64 || defined _M_X64 #define VECTOR_CODING__INTERPOLATION_FILTER 1 ///< enable vector coding for the interpolation filter. 1 (default if SSE possible) disable SSE vector coding. Should not affect RD costs/decisions. Code back-ported from JEM2.0. #define VECTOR_CODING__DISTORTION_CALCULATIONS 1 ///< enable vector coding for distortion calculations 1 (default if SSE possible) disable SSE vector coding. Should not affect RD costs/decisions. Code back-ported from JEM2.0. #else #define VECTOR_CODING__INTERPOLATION_FILTER 0 ///< enable vector coding for the interpolation filter. 0 (default if SSE not possible) disable SSE vector coding. Should not affect RD costs/decisions. Code back-ported from JEM2.0. #define VECTOR_CODING__DISTORTION_CALCULATIONS 0 ///< enable vector coding for distortion calculations 0 (default if SSE not possible) disable SSE vector coding. Should not affect RD costs/decisions. Code back-ported from JEM2.0. #endif // ==================================================================================================================== // Derived macros // ==================================================================================================================== #if RExt__HIGH_BIT_DEPTH_SUPPORT #define FULL_NBIT 1 ///< When enabled, use distortion measure derived from all bits of source data, otherwise discard (bitDepth - 8) least-significant bits of distortion #define RExt__HIGH_PRECISION_FORWARD_TRANSFORM 1 ///< 0 use original 6-bit transform matrices for both forward and inverse transform, 1 (default) = use original matrices for inverse transform and high precision matrices for forward transform #else #define FULL_NBIT 1 ///< When enabled, use distortion measure derived from all bits of source data, otherwise discard (bitDepth - 8) least-significant bits of distortion #define RExt__HIGH_PRECISION_FORWARD_TRANSFORM 0 ///< 0 (default) use original 6-bit transform matrices for both forward and inverse transform, 1 = use original matrices for inverse transform and high precision matrices for forward transform #endif #if FULL_NBIT # define DISTORTION_PRECISION_ADJUSTMENT(x) 0 #else # define DISTORTION_PRECISION_ADJUSTMENT(x) (x) #endif #if DEBUG_STRING #define DEBUG_STRING_PASS_INTO(name) , name #define DEBUG_STRING_PASS_INTO_OPTIONAL(name, exp) , (exp==0)?0:name #define DEBUG_STRING_FN_DECLARE(name) , std::string &name #define DEBUG_STRING_FN_DECLAREP(name) , std::string *name #define DEBUG_STRING_NEW(name) std::string name; #define DEBUG_STRING_OUTPUT(os, name) os << name; #define DEBUG_STRING_APPEND(str1, str2) str1+=str2; #define DEBUG_STRING_SWAP(str1, str2) str1.swap(str2); #define DEBUG_STRING_CHANNEL_CONDITION(compID) (true) #include #include #else #define DEBUG_STRING_PASS_INTO(name) #define DEBUG_STRING_PASS_INTO_OPTIONAL(name, exp) #define DEBUG_STRING_FN_DECLARE(name) #define DEBUG_STRING_FN_DECLAREP(name) #define DEBUG_STRING_NEW(name) #define DEBUG_STRING_OUTPUT(os, name) #define DEBUG_STRING_APPEND(str1, str2) #define DEBUG_STRING_SWAP(srt1, str2) #define DEBUG_STRING_CHANNEL_CONDITION(compID) #endif // ==================================================================================================================== // Error checks // ==================================================================================================================== #if ((RExt__HIGH_PRECISION_FORWARD_TRANSFORM != 0) && (RExt__HIGH_BIT_DEPTH_SUPPORT == 0)) #error ERROR: cannot enable RExt__HIGH_PRECISION_FORWARD_TRANSFORM without RExt__HIGH_BIT_DEPTH_SUPPORT #endif // ==================================================================================================================== // Basic type redefinition // ==================================================================================================================== typedef void Void; typedef bool Bool; typedef char TChar; // Used for text/characters typedef signed char SChar; // Signed 8-bit values typedef unsigned char UChar; // Unsigned 8-bit values typedef short Short; typedef unsigned short UShort; typedef int Int; typedef unsigned int UInt; typedef double Double; typedef float Float; // ==================================================================================================================== // 64-bit integer type // ==================================================================================================================== #ifdef _MSC_VER typedef __int64 Int64; #if _MSC_VER <= 1200 // MS VC6 typedef __int64 UInt64; // MS VC6 does not support unsigned __int64 to double conversion #else typedef unsigned __int64 UInt64; #endif #else typedef long long Int64; typedef unsigned long long UInt64; #endif // ==================================================================================================================== // Named numerical types // ==================================================================================================================== #if RExt__HIGH_BIT_DEPTH_SUPPORT typedef Int Pel; ///< pixel type typedef Int64 TCoeff; ///< transform coefficient typedef Int TMatrixCoeff; ///< transform matrix coefficient typedef Short TFilterCoeff; ///< filter coefficient typedef Int64 Intermediate_Int; ///< used as intermediate value in calculations typedef UInt64 Intermediate_UInt; ///< used as intermediate value in calculations #else typedef Short Pel; ///< pixel type typedef Int TCoeff; ///< transform coefficient typedef Short TMatrixCoeff; ///< transform matrix coefficient typedef Short TFilterCoeff; ///< filter coefficient typedef Int Intermediate_Int; ///< used as intermediate value in calculations typedef UInt Intermediate_UInt; ///< used as intermediate value in calculations #endif #if FULL_NBIT typedef UInt64 Distortion; ///< distortion measurement #else typedef UInt Distortion; ///< distortion measurement #endif // ==================================================================================================================== // Enumeration // ==================================================================================================================== enum RDPCMMode { RDPCM_OFF = 0, RDPCM_HOR = 1, RDPCM_VER = 2, NUMBER_OF_RDPCM_MODES = 3 }; enum RDPCMSignallingMode { RDPCM_SIGNAL_IMPLICIT = 0, RDPCM_SIGNAL_EXPLICIT = 1, NUMBER_OF_RDPCM_SIGNALLING_MODES = 2 }; /// supported slice type enum SliceType { B_SLICE = 0, P_SLICE = 1, I_SLICE = 2, NUMBER_OF_SLICE_TYPES = 3 }; /// chroma formats (according to semantics of chroma_format_idc) enum ChromaFormat { CHROMA_400 = 0, CHROMA_420 = 1, CHROMA_422 = 2, CHROMA_444 = 3, NUM_CHROMA_FORMAT = 4 }; enum ChannelType { CHANNEL_TYPE_LUMA = 0, CHANNEL_TYPE_CHROMA = 1, MAX_NUM_CHANNEL_TYPE = 2 }; enum ComponentID { COMPONENT_Y = 0, COMPONENT_Cb = 1, COMPONENT_Cr = 2, MAX_NUM_COMPONENT = 3 }; enum InputColourSpaceConversion // defined in terms of conversion prior to input of encoder. { IPCOLOURSPACE_UNCHANGED = 0, IPCOLOURSPACE_YCbCrtoYCrCb = 1, // Mainly used for debug! IPCOLOURSPACE_YCbCrtoYYY = 2, // Mainly used for debug! IPCOLOURSPACE_RGBtoGBR = 3, NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS = 4 }; enum MATRIX_COEFFICIENTS // Table E.5 (Matrix coefficients) { MATRIX_COEFFICIENTS_RGB = 0, MATRIX_COEFFICIENTS_BT709 = 1, MATRIX_COEFFICIENTS_UNSPECIFIED = 2, MATRIX_COEFFICIENTS_RESERVED_BY_ITUISOIEC = 3, MATRIX_COEFFICIENTS_USFCCT47 = 4, MATRIX_COEFFICIENTS_BT601_625 = 5, MATRIX_COEFFICIENTS_BT601_525 = 6, MATRIX_COEFFICIENTS_SMPTE240 = 7, MATRIX_COEFFICIENTS_YCGCO = 8, MATRIX_COEFFICIENTS_BT2020_NON_CONSTANT_LUMINANCE = 9, MATRIX_COEFFICIENTS_BT2020_CONSTANT_LUMINANCE = 10, }; enum DeblockEdgeDir { EDGE_VER = 0, EDGE_HOR = 1, NUM_EDGE_DIR = 2 }; /// supported partition shape enum PartSize { SIZE_2Nx2N = 0, ///< symmetric motion partition, 2Nx2N SIZE_2NxN = 1, ///< symmetric motion partition, 2Nx N SIZE_Nx2N = 2, ///< symmetric motion partition, Nx2N SIZE_NxN = 3, ///< symmetric motion partition, Nx N SIZE_2NxnU = 4, ///< asymmetric motion partition, 2Nx( N/2) + 2Nx(3N/2) SIZE_2NxnD = 5, ///< asymmetric motion partition, 2Nx(3N/2) + 2Nx( N/2) SIZE_nLx2N = 6, ///< asymmetric motion partition, ( N/2)x2N + (3N/2)x2N SIZE_nRx2N = 7, ///< asymmetric motion partition, (3N/2)x2N + ( N/2)x2N NUMBER_OF_PART_SIZES = 8 }; /// supported prediction type enum PredMode { MODE_INTER = 0, ///< inter-prediction mode MODE_INTRA = 1, ///< intra-prediction mode NUMBER_OF_PREDICTION_MODES = 2, }; /// reference list index enum RefPicList { REF_PIC_LIST_0 = 0, ///< reference list 0 REF_PIC_LIST_1 = 1, ///< reference list 1 NUM_REF_PIC_LIST_01 = 2, REF_PIC_LIST_X = 100 ///< special mark }; /// distortion function index enum DFunc { DF_DEFAULT = 0, DF_SSE = 1, ///< general size SSE DF_SSE4 = 2, ///< 4xM SSE DF_SSE8 = 3, ///< 8xM SSE DF_SSE16 = 4, ///< 16xM SSE DF_SSE32 = 5, ///< 32xM SSE DF_SSE64 = 6, ///< 64xM SSE DF_SSE16N = 7, ///< 16NxM SSE DF_SAD = 8, ///< general size SAD DF_SAD4 = 9, ///< 4xM SAD DF_SAD8 = 10, ///< 8xM SAD DF_SAD16 = 11, ///< 16xM SAD DF_SAD32 = 12, ///< 32xM SAD DF_SAD64 = 13, ///< 64xM SAD DF_SAD16N = 14, ///< 16NxM SAD DF_SADS = 15, ///< general size SAD with step DF_SADS4 = 16, ///< 4xM SAD with step DF_SADS8 = 17, ///< 8xM SAD with step DF_SADS16 = 18, ///< 16xM SAD with step DF_SADS32 = 19, ///< 32xM SAD with step DF_SADS64 = 20, ///< 64xM SAD with step DF_SADS16N = 21, ///< 16NxM SAD with step DF_HADS = 22, ///< general size Hadamard with step DF_HADS4 = 23, ///< 4xM HAD with step DF_HADS8 = 24, ///< 8xM HAD with step DF_HADS16 = 25, ///< 16xM HAD with step DF_HADS32 = 26, ///< 32xM HAD with step DF_HADS64 = 27, ///< 64xM HAD with step DF_HADS16N = 28, ///< 16NxM HAD with step DF_SAD12 = 43, DF_SAD24 = 44, DF_SAD48 = 45, DF_SADS12 = 46, DF_SADS24 = 47, DF_SADS48 = 48, DF_SSE_FRAME = 50, ///< Frame-based SSE DF_TOTAL_FUNCTIONS = 64 }; /// index for SBAC based RD optimization enum CI_IDX { CI_CURR_BEST = 0, ///< best mode index CI_NEXT_BEST, ///< next best index CI_TEMP_BEST, ///< temporal index CI_CHROMA_INTRA, ///< chroma intra index CI_QT_TRAFO_TEST, CI_QT_TRAFO_ROOT, CI_NUM, ///< total number }; /// motion vector predictor direction used in AMVP enum MVP_DIR { MD_LEFT = 0, ///< MVP of left block MD_ABOVE, ///< MVP of above block MD_ABOVE_RIGHT, ///< MVP of above right block MD_BELOW_LEFT, ///< MVP of below left block MD_ABOVE_LEFT ///< MVP of above left block }; enum StoredResidualType { RESIDUAL_RECONSTRUCTED = 0, RESIDUAL_ENCODER_SIDE = 1, NUMBER_OF_STORED_RESIDUAL_TYPES = 2 }; enum TransformDirection { TRANSFORM_FORWARD = 0, TRANSFORM_INVERSE = 1, TRANSFORM_NUMBER_OF_DIRECTIONS = 2 }; /// supported ME search methods enum MESearchMethod { MESEARCH_FULL = 0, MESEARCH_DIAMOND = 1, MESEARCH_SELECTIVE = 2, MESEARCH_DIAMOND_ENHANCED = 3, MESEARCH_NUMBER_OF_METHODS = 4 }; /// coefficient scanning type used in ACS enum COEFF_SCAN_TYPE { SCAN_DIAG = 0, ///< up-right diagonal scan SCAN_HOR = 1, ///< horizontal first scan SCAN_VER = 2, ///< vertical first scan SCAN_NUMBER_OF_TYPES = 3 }; enum COEFF_SCAN_GROUP_TYPE { SCAN_UNGROUPED = 0, SCAN_GROUPED_4x4 = 1, SCAN_NUMBER_OF_GROUP_TYPES = 2 }; enum SignificanceMapContextType { CONTEXT_TYPE_4x4 = 0, CONTEXT_TYPE_8x8 = 1, CONTEXT_TYPE_NxN = 2, CONTEXT_TYPE_SINGLE = 3, CONTEXT_NUMBER_OF_TYPES = 4 }; enum ScalingListMode { SCALING_LIST_OFF, SCALING_LIST_DEFAULT, SCALING_LIST_FILE_READ }; enum ScalingListSize { SCALING_LIST_4x4 = 0, SCALING_LIST_8x8, SCALING_LIST_16x16, SCALING_LIST_32x32, SCALING_LIST_SIZE_NUM }; // Slice / Slice segment encoding modes enum SliceConstraint { NO_SLICES = 0, ///< don't use slices / slice segments FIXED_NUMBER_OF_CTU = 1, ///< Limit maximum number of largest coding tree units in a slice / slice segments FIXED_NUMBER_OF_BYTES = 2, ///< Limit maximum number of bytes in a slice / slice segment FIXED_NUMBER_OF_TILES = 3, ///< slices / slice segments span an integer number of tiles NUMBER_OF_SLICE_CONSTRAINT_MODES = 4 }; // For use with decoded picture hash SEI messages, generated by encoder. enum HashType { HASHTYPE_MD5 = 0, HASHTYPE_CRC = 1, HASHTYPE_CHECKSUM = 2, HASHTYPE_NONE = 3, NUMBER_OF_HASHTYPES = 4 }; enum SAOMode //mode { SAO_MODE_OFF = 0, SAO_MODE_NEW, SAO_MODE_MERGE, NUM_SAO_MODES }; enum SAOModeMergeTypes { SAO_MERGE_LEFT =0, SAO_MERGE_ABOVE, NUM_SAO_MERGE_TYPES }; enum SAOModeNewTypes { SAO_TYPE_START_EO =0, SAO_TYPE_EO_0 = SAO_TYPE_START_EO, SAO_TYPE_EO_90, SAO_TYPE_EO_135, SAO_TYPE_EO_45, SAO_TYPE_START_BO, SAO_TYPE_BO = SAO_TYPE_START_BO, NUM_SAO_NEW_TYPES }; #define NUM_SAO_EO_TYPES_LOG2 2 enum SAOEOClasses { SAO_CLASS_EO_FULL_VALLEY = 0, SAO_CLASS_EO_HALF_VALLEY = 1, SAO_CLASS_EO_PLAIN = 2, SAO_CLASS_EO_HALF_PEAK = 3, SAO_CLASS_EO_FULL_PEAK = 4, NUM_SAO_EO_CLASSES, }; #define NUM_SAO_BO_CLASSES_LOG2 5 #define NUM_SAO_BO_CLASSES (1< NUM_SAO_BO_GROUPS)?NUM_SAO_EO_GROUPS:NUM_SAO_BO_GROUPS struct SAOOffset { SAOMode modeIdc; // NEW, MERGE, OFF Int typeIdc; // union of SAOModeMergeTypes and SAOModeNewTypes, depending on modeIdc. Int typeAuxInfo; // BO: starting band index Int offset[MAX_NUM_SAO_CLASSES]; SAOOffset(); ~SAOOffset(); Void reset(); const SAOOffset& operator= (const SAOOffset& src); }; struct SAOBlkParam { SAOBlkParam(); ~SAOBlkParam(); Void reset(); const SAOBlkParam& operator= (const SAOBlkParam& src); SAOOffset& operator[](Int compIdx){ return offsetParam[compIdx];} private: SAOOffset offsetParam[MAX_NUM_COMPONENT]; }; struct BitDepths { #if JVET_X0048_X0103_FILM_GRAIN const int &operator[](const ChannelType ch) const { return recon[ch]; } #endif #if O0043_BEST_EFFORT_DECODING Int recon[MAX_NUM_CHANNEL_TYPE]; ///< the bit depth used for reconstructing the video Int stream[MAX_NUM_CHANNEL_TYPE];///< the bit depth used indicated in the SPS #else Int recon[MAX_NUM_CHANNEL_TYPE]; ///< the bit depth as indicated in the SPS #endif }; /// parameters for deblocking filter typedef struct _LFCUParam { Bool bInternalEdge; ///< indicates internal edge Bool bLeftEdge; ///< indicates left edge Bool bTopEdge; ///< indicates top edge } LFCUParam; //TU settings for entropy encoding struct TUEntropyCodingParameters { const UInt *scan; const UInt *scanCG; COEFF_SCAN_TYPE scanType; UInt widthInGroups; UInt heightInGroups; UInt firstSignificanceMapContext; }; struct TComPictureHash { std::vector hash; Bool operator==(const TComPictureHash &other) const { if (other.hash.size() != hash.size()) { return false; } for(UInt i=0; i > mapping; ///< first=luma level, second=delta QP. Bool isEnabled() const { return mode!=LUMALVL_TO_DQP_DISABLED; } }; struct WCGChromaQPControl { Bool isEnabled() const { return enabled; } Bool enabled; ///< Enabled flag (0:default) Double chromaCbQpScale; ///< Chroma Cb QP Scale (1.0:default) Double chromaCrQpScale; ///< Chroma Cr QP Scale (1.0:default) Double chromaQpScale; ///< Chroma QP Scale (0.0:default) Double chromaQpOffset; ///< Chroma QP Offset (0.0:default) }; struct TComSEIFisheyeVideoInfo { struct ActiveAreaInfo { UInt m_fisheyeCircularRegionCentreX; UInt m_fisheyeCircularRegionCentreY; UInt m_fisheyeRectRegionTop; UInt m_fisheyeRectRegionLeft; UInt m_fisheyeRectRegionWidth; UInt m_fisheyeRectRegionHeight; UInt m_fisheyeCircularRegionRadius; UInt m_fisheyeSceneRadius; Int m_fisheyeCameraCentreAzimuth; Int m_fisheyeCameraCentreElevation; Int m_fisheyeCameraCentreTilt; UInt m_fisheyeCameraCentreOffsetX; UInt m_fisheyeCameraCentreOffsetY; UInt m_fisheyeCameraCentreOffsetZ; UInt m_fisheyeFieldOfView; std::vector m_fisheyePolynomialCoeff; }; Bool m_fisheyeCancelFlag; Bool m_fisheyePersistenceFlag; UInt m_fisheyeViewDimensionIdc; std::vector m_fisheyeActiveAreas; TComSEIFisheyeVideoInfo() : m_fisheyeCancelFlag(false), m_fisheyePersistenceFlag(false), m_fisheyeViewDimensionIdc(0), m_fisheyeActiveAreas() { } }; class Window { private: Bool m_enabledFlag; Int m_winLeftOffset; Int m_winRightOffset; Int m_winTopOffset; Int m_winBottomOffset; public: Window() : m_enabledFlag (false) , m_winLeftOffset (0) , m_winRightOffset (0) , m_winTopOffset (0) , m_winBottomOffset(0) { } Bool getWindowEnabledFlag() const { return m_enabledFlag; } Int getWindowLeftOffset() const { return m_enabledFlag ? m_winLeftOffset : 0; } Void setWindowLeftOffset(Int val) { m_winLeftOffset = val; m_enabledFlag = true; } Int getWindowRightOffset() const { return m_enabledFlag ? m_winRightOffset : 0; } Void setWindowRightOffset(Int val) { m_winRightOffset = val; m_enabledFlag = true; } Int getWindowTopOffset() const { return m_enabledFlag ? m_winTopOffset : 0; } Void setWindowTopOffset(Int val) { m_winTopOffset = val; m_enabledFlag = true; } Int getWindowBottomOffset() const { return m_enabledFlag ? m_winBottomOffset: 0; } Void setWindowBottomOffset(Int val) { m_winBottomOffset = val; m_enabledFlag = true; } Void setWindow(Int offsetLeft, Int offsetRight, Int offsetTop, Int offsetBottom) { m_enabledFlag = (offsetLeft || offsetRight || offsetTop || offsetBottom); m_winLeftOffset = offsetLeft; m_winRightOffset = offsetRight; m_winTopOffset = offsetTop; m_winBottomOffset = offsetBottom; } Bool operator == (const Window &rhs) const { return ( m_enabledFlag && rhs.m_enabledFlag && m_winLeftOffset == rhs.m_winLeftOffset && m_winRightOffset == rhs.m_winRightOffset && m_winTopOffset == rhs.m_winTopOffset && m_winBottomOffset == rhs.m_winBottomOffset ); } }; class RNSEIWindow : public Window { private: UInt m_regionId; public: RNSEIWindow() : Window(), m_regionId(0) {} Int getRegionId() const { return getWindowEnabledFlag() ? m_regionId : 0; } Void setRegionId(UInt const val) { m_regionId = val; } // Check two RNSEIWindows are identical Bool operator == (RNSEIWindow const &rhs) const { return ( (m_regionId == rhs.m_regionId) && Window(*this) == Window(rhs) ); } // Check if two windows are identical, even though regions may be different Bool checkSameRegion(RNSEIWindow const &rhs) const { return ( Window(*this) == Window(rhs) ); } Bool checkSameID(RNSEIWindow const &rhs) const { return ( m_regionId == rhs.m_regionId ); } friend std::ostream& operator<<(std::ostream &os, RNSEIWindow const ®ion); }; typedef std::vector RNSEIWindowVec; //! \} #endif HM-HM-18.0/source/Lib/TLibCommonAnalyser/000077500000000000000000000000001442026013100177515ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibCommonAnalyser/CMakeLists.txt000066400000000000000000000063661442026013100225240ustar00rootroot00000000000000# library set( LIB_NAME TLibCommonAnalyser ) # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # get source files file( GLOB BASE_SRC_FILES "../TLibCommon/*.cpp" ) # get include files file( GLOB BASE_INC_FILES "../TLibCommon/*.h" ) # get x86 source files file( GLOB X86_SRC_FILES "../TLibCommon/x86/*.cpp" ) # get x86 include files file( GLOB X86_INC_FILES "../TLibCommon/x86/*.h" ) # get avx source files file( GLOB AVX_SRC_FILES "../TLibCommon/x86/avx/*.cpp" ) # get avx2 source files file( GLOB AVX2_SRC_FILES "../TLibCommon/x86/avx2/*.cpp" ) # get sse4.1 source files file( GLOB SSE41_SRC_FILES "../TLibCommon/x86/sse41/*.cpp" ) # get sse4.2 source files file( GLOB SSE42_SRC_FILES "../TLibCommon/x86/sse42/*.cpp" ) # get libmd5 source files file( GLOB MD5_SRC_FILES "../libmd5/*.cpp" ) # get libmd5 include files file( GLOB MD5_INC_FILES "../libmd5/*.h" ) # get all source files set( SRC_FILES ${BASE_SRC_FILES} ${X86_SRC_FILES} ${SSE41_SRC_FILES} ${SSE42_SRC_FILES} ${AVX_SRC_FILES} ${AVX2_SRC_FILES} ${MD5_SRC_FILES} ) # get all include files set( INC_FILES ${BASE_INC_FILES} ${X86_INC_FILES} ${MD5_INC_FILES} ) # library add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__DECODER_DEBUG_BIT_STATISTICS=1 ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__DECODER_DEBUG_TOOL_STATISTICS=1 ) if( HIGH_BITDEPTH ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( EXTENSION_360_VIDEO ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 ) endif() if( EXTENSION_HDRTOOLS ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_HDRTOOLS=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() target_include_directories( ${LIB_NAME} PUBLIC . .. ../TLibCommon/ ../TLibCommon/x86 ../libmd5 ) target_link_libraries( ${LIB_NAME} Threads::Threads ) # set needed compile definitions set_property( SOURCE ${SSE41_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_SSE41 ) set_property( SOURCE ${SSE42_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_SSE42 ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_AVX ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_DEFINITIONS USE_AVX2 ) # set needed compile flags if( MSVC ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "/arch:AVX" ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "/arch:AVX2" ) elseif( UNIX OR MINGW ) set_property( SOURCE ${SSE41_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-msse4.1" ) set_property( SOURCE ${SSE42_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-msse4.2" ) set_property( SOURCE ${AVX_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-mavx" ) set_property( SOURCE ${AVX2_SRC_FILES} APPEND PROPERTY COMPILE_FLAGS "-mavx2" ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib ) HM-HM-18.0/source/Lib/TLibDecoder/000077500000000000000000000000001442026013100163675ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibDecoder/AnnexBread.cpp000066400000000000000000000171531442026013100211110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file AnnexBread.cpp \brief reading functions for Annex B byte streams */ #include #include #include #include "AnnexBread.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif using namespace std; //! \ingroup TLibDecoder //! \{ /** * Parse an AVC AnnexB Bytestream bs to extract a single nalUnit * while accumulating bytestream statistics into stats. * * If EOF occurs while trying to extract a NALunit, an exception * of std::ios_base::failure is thrown. The contsnts of stats will * be correct at this point. */ static Void _byteStreamNALUnit( InputByteStream& bs, vector& nalUnit, AnnexBStats& stats) { /* At the beginning of the decoding process, the decoder initialises its * current position in the byte stream to the beginning of the byte stream. * It then extracts and discards each leading_zero_8bits syntax element (if * present), moving the current position in the byte stream forward one * byte at a time, until the current position in the byte stream is such * that the next four bytes in the bitstream form the four-byte sequence * 0x00000001. */ #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::SStat &statBits=TComCodingStatistics::GetStatisticEP(STATS__NAL_UNIT_PACKING); #endif while ((bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) != 0x000001) && (bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001)) { uint8_t leading_zero_8bits = bs.readByte(); #if RExt__DECODER_DEBUG_BIT_STATISTICS statBits.bits+=8; statBits.count++; #endif assert(leading_zero_8bits == 0); stats.m_numLeadingZero8BitsBytes++; } /* 1. When the next four bytes in the bitstream form the four-byte sequence * 0x00000001, the next byte in the byte stream (which is a zero_byte * syntax element) is extracted and discarded and the current position in * the byte stream is set equal to the position of the byte following this * discarded byte. */ /* NB, the previous step guarantees this will succeed -- if EOF was * encountered, an exception will stop execution getting this far */ if (bs.peekBytes(24/8) != 0x000001) { uint8_t zero_byte = bs.readByte(); #if RExt__DECODER_DEBUG_BIT_STATISTICS statBits.bits+=8; statBits.count++; #endif assert(zero_byte == 0); stats.m_numZeroByteBytes++; } /* 2. The next three-byte sequence in the byte stream (which is a * start_code_prefix_one_3bytes) is extracted and discarded and the current * position in the byte stream is set equal to the position of the byte * following this three-byte sequence. */ /* NB, (1) guarantees that the next three bytes are 0x00 00 01 */ uint32_t start_code_prefix_one_3bytes = bs.readBytes(24/8); #if RExt__DECODER_DEBUG_BIT_STATISTICS statBits.bits+=24; statBits.count+=3; #endif assert(start_code_prefix_one_3bytes == 0x000001); stats.m_numStartCodePrefixBytes += 3; /* 3. NumBytesInNALunit is set equal to the number of bytes starting with * the byte at the current position in the byte stream up to and including * the last byte that precedes the location of any of the following * conditions: * a. A subsequent byte-aligned three-byte sequence equal to 0x000000, or * b. A subsequent byte-aligned three-byte sequence equal to 0x000001, or * c. The end of the byte stream, as determined by unspecified means. */ /* 4. NumBytesInNALunit bytes are removed from the bitstream and the * current position in the byte stream is advanced by NumBytesInNALunit * bytes. This sequence of bytes is nal_unit( NumBytesInNALunit ) and is * decoded using the NAL unit decoding process */ /* NB, (unsigned)x > 2 implies n!=0 && n!=1 */ #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::SStat &bodyStats=TComCodingStatistics::GetStatisticEP(STATS__NAL_UNIT_TOTAL_BODY); #endif while (bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) > 2) { #if RExt__DECODER_DEBUG_BIT_STATISTICS uint8_t thebyte=bs.readByte();bodyStats.bits+=8;bodyStats.count++; nalUnit.push_back(thebyte); #else nalUnit.push_back(bs.readByte()); #endif } /* 5. When the current position in the byte stream is: * - not at the end of the byte stream (as determined by unspecified means) * - and the next bytes in the byte stream do not start with a three-byte * sequence equal to 0x000001 * - and the next bytes in the byte stream do not start with a four byte * sequence equal to 0x00000001, * the decoder extracts and discards each trailing_zero_8bits syntax * element, moving the current position in the byte stream forward one byte * at a time, until the current position in the byte stream is such that: * - the next bytes in the byte stream form the four-byte sequence * 0x00000001 or * - the end of the byte stream has been encountered (as determined by * unspecified means). */ /* NB, (3) guarantees there are at least three bytes available or none */ while ((bs.eofBeforeNBytes(24/8) || bs.peekBytes(24/8) != 0x000001) && (bs.eofBeforeNBytes(32/8) || bs.peekBytes(32/8) != 0x00000001)) { uint8_t trailing_zero_8bits = bs.readByte(); #if RExt__DECODER_DEBUG_BIT_STATISTICS statBits.bits+=8; statBits.count++; #endif assert(trailing_zero_8bits == 0); stats.m_numTrailingZero8BitsBytes++; } } /** * Parse an AVC AnnexB Bytestream bs to extract a single nalUnit * while accumulating bytestream statistics into stats. * * Returns false if EOF was reached (NB, nalunit data may be valid), * otherwise true. */ Bool byteStreamNALUnit( InputByteStream& bs, vector& nalUnit, AnnexBStats& stats) { Bool eof = false; try { _byteStreamNALUnit(bs, nalUnit, stats); } catch (...) { eof = true; } stats.m_numBytesInNALUnit = UInt(nalUnit.size()); return eof; } //! \} HM-HM-18.0/source/Lib/TLibDecoder/AnnexBread.h000066400000000000000000000126501442026013100205530ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file AnnexBread.h \brief reading functions for Annex B byte streams */ #pragma once #ifndef __ANNEXBREAD__ #define __ANNEXBREAD__ #include #include #include #include "TLibCommon/CommonDef.h" //! \ingroup TLibDecoder //! \{ class InputByteStream { public: /** * Create a bytestream reader that will extract bytes from * istream. * * NB, it isn't safe to access istream while in use by a * InputByteStream. * * Side-effects: the exception mask of istream is set to eofbit */ InputByteStream(std::istream& istream) : m_NumFutureBytes(0) , m_FutureBytes(0) , m_Input(istream) { istream.exceptions(std::istream::eofbit | std::istream::badbit); } /** * Reset the internal state. Must be called if input stream is * modified externally to this class */ Void reset() { m_NumFutureBytes = 0; m_FutureBytes = 0; } /** * returns true if an EOF will be encountered within the next * n bytes. */ Bool eofBeforeNBytes(UInt n) { assert(n <= 4); if (m_NumFutureBytes >= n) { return false; } n -= m_NumFutureBytes; try { for (UInt i = 0; i < n; i++) { m_FutureBytes = (m_FutureBytes << 8) | m_Input.get(); m_NumFutureBytes++; } } catch (...) { return true; } return false; } /** * return the next n bytes in the stream without advancing * the stream pointer. * * Returns: an unsigned integer representing an n byte bigendian * word. * * If an attempt is made to read past EOF, an n-byte word is * returned, but the portion that required input bytes beyond EOF * is undefined. * */ uint32_t peekBytes(UInt n) { eofBeforeNBytes(n); return m_FutureBytes >> 8*(m_NumFutureBytes - n); } /** * consume and return one byte from the input. * * If bytestream is already at EOF prior to a call to readByte(), * an exception std::ios_base::failure is thrown. */ uint8_t readByte() { if (!m_NumFutureBytes) { uint8_t byte = m_Input.get(); return byte; } m_NumFutureBytes--; uint8_t wanted_byte = m_FutureBytes >> 8*m_NumFutureBytes; m_FutureBytes &= ~(0xff << 8*m_NumFutureBytes); return wanted_byte; } /** * consume and return n bytes from the input. n bytes from * bytestream are interpreted as bigendian when assembling * the return value. */ uint32_t readBytes(UInt n) { uint32_t val = 0; for (UInt i = 0; i < n; i++) { val = (val << 8) | readByte(); } return val; } #if RExt__DECODER_DEBUG_BIT_STATISTICS UInt GetNumBufferedBytes() const { return m_NumFutureBytes; } #endif private: UInt m_NumFutureBytes; /* number of valid bytes in m_FutureBytes */ uint32_t m_FutureBytes; /* bytes that have been peeked */ std::istream& m_Input; /* Input stream to read from */ }; /** * Statistics associated with AnnexB bytestreams */ struct AnnexBStats { UInt m_numLeadingZero8BitsBytes; UInt m_numZeroByteBytes; UInt m_numStartCodePrefixBytes; UInt m_numBytesInNALUnit; UInt m_numTrailingZero8BitsBytes; AnnexBStats& operator+=(const AnnexBStats& rhs) { this->m_numLeadingZero8BitsBytes += rhs.m_numLeadingZero8BitsBytes; this->m_numZeroByteBytes += rhs.m_numZeroByteBytes; this->m_numStartCodePrefixBytes += rhs.m_numStartCodePrefixBytes; this->m_numBytesInNALUnit += rhs.m_numBytesInNALUnit; this->m_numTrailingZero8BitsBytes += rhs.m_numTrailingZero8BitsBytes; return *this; } }; Bool byteStreamNALUnit(InputByteStream& bs, std::vector& nalUnit, AnnexBStats& stats); //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/CMakeLists.txt000066400000000000000000000021761442026013100211350ustar00rootroot00000000000000# library set( LIB_NAME TLibDecoder ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # library add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) target_compile_definitions( ${LIB_NAME} PUBLIC ) if( HIGH_BITDEPTH ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( EXTENSION_360_VIDEO ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() target_include_directories( ${LIB_NAME} PUBLIC . ) target_link_libraries( ${LIB_NAME} TLibCommon Threads::Threads ) # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib ) HM-HM-18.0/source/Lib/TLibDecoder/NALread.cpp000066400000000000000000000143051442026013100203440ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file NALread.cpp \brief reading functionality for NAL units */ #include #include #include #include "NALread.h" #include "TLibCommon/NAL.h" #include "TLibCommon/TComBitStream.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif #if ENC_DEC_TRACE && DEC_NUH_TRACE #include "TLibCommon/TComRom.h" #endif using namespace std; //! \ingroup TLibDecoder //! \{ static Void convertPayloadToRBSP(vector& nalUnitBuf, TComInputBitstream *bitstream, Bool isVclNalUnit) { UInt zeroCount = 0; vector::iterator it_read, it_write; UInt pos = 0; bitstream->clearEmulationPreventionByteLocation(); for (it_read = it_write = nalUnitBuf.begin(); it_read != nalUnitBuf.end(); it_read++, it_write++, pos++) { assert(zeroCount < 2 || *it_read >= 0x03); if (zeroCount == 2 && *it_read == 0x03) { bitstream->pushEmulationPreventionByteLocation( pos ); pos++; it_read++; zeroCount = 0; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(STATS__EMULATION_PREVENTION_3_BYTES, 8, 0); #endif if (it_read == nalUnitBuf.end()) { break; } assert(*it_read <= 0x03); } zeroCount = (*it_read == 0x00) ? zeroCount+1 : 0; *it_write = *it_read; } assert(zeroCount == 0); if (isVclNalUnit) { // Remove cabac_zero_word from payload if present Int n = 0; while (it_write[-1] == 0x00) { it_write--; n++; } if (n > 0) { printf("\nDetected %d instances of cabac_zero_word\n", n/2); } } nalUnitBuf.resize(it_write - nalUnitBuf.begin()); } #if ENC_DEC_TRACE && DEC_NUH_TRACE void xTraceNalUnitHeader(InputNALUnit& nalu) { fprintf( g_hTrace, "*********** NAL UNIT (%s) ***********\n", nalUnitTypeToString(nalu.m_nalUnitType) ); fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(%d) : %u\n", "forbidden_zero_bit", 1, 0 ); fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(%d) : %u\n", "nal_unit_type", 6, nalu.m_nalUnitType ); fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(%d) : %u\n", "nuh_layer_id", 6, nalu.m_nuhLayerId ); fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(%d) : %u\n", "nuh_temporal_id_plus1", 3, nalu.m_temporalId + 1 ); fflush ( g_hTrace ); } #endif Void readNalUnitHeader(InputNALUnit& nalu) { TComInputBitstream& bs = nalu.getBitstream(); Bool forbidden_zero_bit = bs.read(1); // forbidden_zero_bit assert(forbidden_zero_bit == 0); nalu.m_nalUnitType = (NalUnitType) bs.read(6); // nal_unit_type nalu.m_nuhLayerId = bs.read(6); // nuh_layer_id nalu.m_temporalId = bs.read(3) - 1; // nuh_temporal_id_plus1 #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(STATS__NAL_UNIT_HEADER_BITS, 1+6+6+3, 0); #endif #if ENC_DEC_TRACE && DEC_NUH_TRACE xTraceNalUnitHeader(nalu); #endif // only check these rules for base layer if (nalu.m_nuhLayerId == 0) { if ( nalu.m_temporalId ) { assert( nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLA_W_LP && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLA_W_RADL && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_BLA_N_LP && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR_W_RADL && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_IDR_N_LP && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_CRA && nalu.m_nalUnitType != NAL_UNIT_VPS && nalu.m_nalUnitType != NAL_UNIT_SPS && nalu.m_nalUnitType != NAL_UNIT_EOS && nalu.m_nalUnitType != NAL_UNIT_EOB ); } else { assert( nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_TSA_R && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_TSA_N && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_STSA_R && nalu.m_nalUnitType != NAL_UNIT_CODED_SLICE_STSA_N ); } } } /** * create a NALunit structure with given header values and storage for * a bitstream */ Void read(InputNALUnit& nalu) { TComInputBitstream &bitstream = nalu.getBitstream(); vector& nalUnitBuf=bitstream.getFifo(); // perform anti-emulation prevention convertPayloadToRBSP(nalUnitBuf, &bitstream, (nalUnitBuf[0] & 64) == 0); bitstream.resetToStart(); readNalUnitHeader(nalu); } //! \} HM-HM-18.0/source/Lib/TLibDecoder/NALread.h000066400000000000000000000052011442026013100200040ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file NALread.h \brief reading functionality for NAL units */ #pragma once #ifndef __NALREAD__ #define __NALREAD__ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/NAL.h" //! \ingroup TLibDecoder //! \{ /** * A convenience wrapper to NALUnit that also provides a * bitstream object. */ class InputNALUnit : public NALUnit { private: TComInputBitstream m_Bitstream; public: InputNALUnit(const InputNALUnit &src) : NALUnit(src), m_Bitstream(src.m_Bitstream) {}; InputNALUnit() : m_Bitstream() {}; virtual ~InputNALUnit() { } const TComInputBitstream &getBitstream() const { return m_Bitstream; } TComInputBitstream &getBitstream() { return m_Bitstream; } }; Void read(InputNALUnit& nalu); Void readNalUnitHeader(InputNALUnit& nalu); //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/SEIread.cpp000066400000000000000000003170501442026013100203550ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIread.cpp \brief reading functionality for SEI messages */ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/SEI.h" #include "TLibCommon/TComSlice.h" #include "SyntaxElementParser.h" #include "SEIread.h" #include "TLibCommon/TComPicYuv.h" #include //! \ingroup TLibDecoder //! \{ #if ENC_DEC_TRACE Void xTraceSEIHeader() { fprintf( g_hTrace, "=========== SEI message ===========\n"); } Void xTraceSEIMessageType(SEI::PayloadType payloadType) { fprintf( g_hTrace, "=========== %s SEI message ===========\n", SEI::getSEIMessageString(payloadType)); } #endif Void SEIReader::sei_read_scode(std::ostream *pOS, UInt uiLength, Int& ruiCode, const TChar *pSymbolName) { READ_SCODE(uiLength, ruiCode, pSymbolName); if (pOS) { (*pOS) << " " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n"; } } Void SEIReader::sei_read_code(std::ostream *pOS, UInt uiLength, UInt& ruiCode, const TChar *pSymbolName) { READ_CODE(uiLength, ruiCode, pSymbolName); if (pOS) { (*pOS) << " " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n"; } } Void SEIReader::sei_read_uvlc(std::ostream *pOS, UInt& ruiCode, const TChar *pSymbolName) { READ_UVLC(ruiCode, pSymbolName); if (pOS) { (*pOS) << " " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n"; } } Void SEIReader::sei_read_svlc(std::ostream *pOS, Int& ruiCode, const TChar *pSymbolName) { READ_SVLC(ruiCode, pSymbolName); if (pOS) { (*pOS) << " " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n"; } } Void SEIReader::sei_read_flag(std::ostream *pOS, UInt& ruiCode, const TChar *pSymbolName) { READ_FLAG(ruiCode, pSymbolName); if (pOS) { (*pOS) << " " << std::setw(55) << pSymbolName << ": " << (ruiCode?1:0) << "\n"; } } static inline Void output_sei_message_header(SEI &sei, std::ostream *pDecodedMessageOutputStream, UInt payloadSize) { if (pDecodedMessageOutputStream) { std::string seiMessageHdr(SEI::getSEIMessageString(sei.payloadType())); seiMessageHdr+=" SEI message"; (*pDecodedMessageOutputStream) << std::setfill('-') << std::setw((int)seiMessageHdr.size()) << "-" << std::setfill(' ') << "\n" << seiMessageHdr << " (" << payloadSize << " bytes)"<< "\n"; } } #undef READ_SCODE #undef READ_CODE #undef READ_SVLC #undef READ_UVLC #undef READ_FLAG /** * unmarshal a single SEI message from bitstream bs */ Void SEIReader::parseSEImessage(TComInputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream) { setBitstream(bs); assert(!m_pcBitstream->getNumBitsUntilByteAligned()); do { if(nalUnitType == NAL_UNIT_PREFIX_SEI) { xReadSEImessage(seis, nalUnitType, sps, pDecodedMessageOutputStream, SEI::prefix_sei_messages, std::string("prefix SEI")); } else if (nalUnitType == NAL_UNIT_SUFFIX_SEI) { xReadSEImessage(seis, nalUnitType, sps, pDecodedMessageOutputStream, SEI::suffix_sei_messages, std::string("suffix SEI")); } else { std::cerr << "Unsupported SEI NAL unit type '" << nalUnitType << "'" << std::endl; exit(EXIT_FAILURE); } /* SEI messages are an integer number of bytes, something has failed * in the parsing if bitstream not byte-aligned */ assert(!m_pcBitstream->getNumBitsUntilByteAligned()); } while (m_pcBitstream->getNumBitsLeft() > 8); xReadRbspTrailingBits(); } Void SEIReader::xReadSEIPayloadData(Int const payloadType, Int const payloadSize, SEI *&sei, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream, std::string const &typeName) { switch(payloadType) { case SEI::BUFFERING_PERIOD: if (!sps) { printf ("Warning: Found Buffering period SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIBufferingPeriod; xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, sps, pDecodedMessageOutputStream); } break; case SEI::PICTURE_TIMING: if (!sps) { printf ("Warning: Found Picture timing SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIPictureTiming; xParseSEIPictureTiming((SEIPictureTiming&)*sei, payloadSize, sps, pDecodedMessageOutputStream); } break; case SEI::PAN_SCAN_RECT: sei = new SEIPanScanRect; xParseSEIPanScanRect((SEIPanScanRect&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::FILLER_PAYLOAD: sei = new SEIFillerPayload; xParseSEIFillerPayload((SEIFillerPayload&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::USER_DATA_REGISTERED_ITU_T_T35: sei = new SEIUserDataRegistered; xParseSEIUserDataRegistered((SEIUserDataRegistered&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::USER_DATA_UNREGISTERED: sei = new SEIUserDataUnregistered; xParseSEIUserDataUnregistered((SEIUserDataUnregistered&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::RECOVERY_POINT: sei = new SEIRecoveryPoint; xParseSEIRecoveryPoint((SEIRecoveryPoint&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::SCENE_INFO: sei = new SEISceneInfo; xParseSEISceneInfo((SEISceneInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::PICTURE_SNAPSHOT: sei = new SEIPictureSnapshot; xParseSEIPictureSnapshot((SEIPictureSnapshot&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_START: sei = new SEIProgressiveRefinementSegmentStart; xParseSEIProgressiveRefinementSegmentStart((SEIProgressiveRefinementSegmentStart&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_END: sei = new SEIProgressiveRefinementSegmentEnd; xParseSEIProgressiveRefinementSegmentEnd((SEIProgressiveRefinementSegmentEnd&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::FILM_GRAIN_CHARACTERISTICS: sei = new SEIFilmGrainCharacteristics; xParseSEIFilmGrainCharacteristics((SEIFilmGrainCharacteristics&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::POST_FILTER_HINT: if (!sps) { printf ("Warning: post filter hint SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIPostFilterHint; xParseSEIPostFilterHint((SEIPostFilterHint&) *sei, payloadSize, sps, pDecodedMessageOutputStream); } break; case SEI::TONE_MAPPING_INFO: sei = new SEIToneMappingInfo; xParseSEIToneMappingInfo((SEIToneMappingInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::FRAME_PACKING: sei = new SEIFramePacking; xParseSEIFramePacking((SEIFramePacking&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::DISPLAY_ORIENTATION: sei = new SEIDisplayOrientation; xParseSEIDisplayOrientation((SEIDisplayOrientation&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::GREEN_METADATA: sei = new SEIGreenMetadataInfo; xParseSEIGreenMetadataInfo((SEIGreenMetadataInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::SOP_DESCRIPTION: sei = new SEISOPDescription; xParseSEISOPDescription((SEISOPDescription&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::DECODED_PICTURE_HASH: sei = new SEIDecodedPictureHash; xParseSEIDecodedPictureHash((SEIDecodedPictureHash&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::ACTIVE_PARAMETER_SETS: sei = new SEIActiveParameterSets; xParseSEIActiveParameterSets((SEIActiveParameterSets&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::DECODING_UNIT_INFO: if (!sps) { printf ("Warning: Found Decoding unit SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIDecodingUnitInfo; xParseSEIDecodingUnitInfo((SEIDecodingUnitInfo&) *sei, payloadSize, sps, pDecodedMessageOutputStream); } break; case SEI::TEMPORAL_LEVEL0_INDEX: sei = new SEITemporalLevel0Index; xParseSEITemporalLevel0Index((SEITemporalLevel0Index&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::SCALABLE_NESTING: sei = new SEIScalableNesting; xParseSEIScalableNesting((SEIScalableNesting&) *sei, nalUnitType, payloadSize, sps, pDecodedMessageOutputStream); break; case SEI::REGION_REFRESH_INFO: sei = new SEIRegionRefreshInfo; xParseSEIRegionRefreshInfo((SEIRegionRefreshInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::NO_DISPLAY: sei = new SEINoDisplay; xParseSEINoDisplay((SEINoDisplay&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::TIME_CODE: sei = new SEITimeCode; xParseSEITimeCode((SEITimeCode&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::MASTERING_DISPLAY_COLOUR_VOLUME: sei = new SEIMasteringDisplayColourVolume; xParseSEIMasteringDisplayColourVolume((SEIMasteringDisplayColourVolume&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::SEGM_RECT_FRAME_PACKING: sei = new SEISegmentedRectFramePacking; xParseSEISegmentedRectFramePacking((SEISegmentedRectFramePacking&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS: sei = new SEITempMotionConstrainedTileSets; xParseSEITempMotionConstraintsTileSets((SEITempMotionConstrainedTileSets&) *sei, payloadSize, pDecodedMessageOutputStream); break; #if MCTS_EXTRACTION case SEI::MCTS_EXTRACTION_INFO_SET: sei = new SEIMCTSExtractionInfoSet; xParseSEIMCTSExtractionInfoSet((SEIMCTSExtractionInfoSet&)*sei, payloadSize, pDecodedMessageOutputStream); break; #endif case SEI::CHROMA_RESAMPLING_FILTER_HINT: sei = new SEIChromaResamplingFilterHint; xParseSEIChromaResamplingFilterHint((SEIChromaResamplingFilterHint&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::KNEE_FUNCTION_INFO: sei = new SEIKneeFunctionInfo; xParseSEIKneeFunctionInfo((SEIKneeFunctionInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::COLOUR_REMAPPING_INFO: sei = new SEIColourRemappingInfo; xParseSEIColourRemappingInfo((SEIColourRemappingInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::DEINTERLACE_FIELD_IDENTIFICATION: sei = new SEIDeinterlaceFieldIdentification; xParseSEIDeinterlaceFieldIdentification((SEIDeinterlaceFieldIdentification&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::CONTENT_LIGHT_LEVEL_INFO: sei = new SEIContentLightLevelInfo; xParseSEIContentLightLevelInfo((SEIContentLightLevelInfo&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::DEPENDENT_RAP_INDICATION: sei = new SEIDependentRAPIndication; xParseSEIDependentRAPIndication((SEIDependentRAPIndication&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::CODED_REGION_COMPLETION: sei = new SEICodedRegionCompletion; xParseSEICodedRegionCompletion((SEICodedRegionCompletion&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS: sei = new SEIAlternativeTransferCharacteristics; xParseSEIAlternativeTransferCharacteristics((SEIAlternativeTransferCharacteristics&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::AMBIENT_VIEWING_ENVIRONMENT: sei = new SEIAmbientViewingEnvironment; xParseSEIAmbientViewingEnvironment((SEIAmbientViewingEnvironment&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::CONTENT_COLOUR_VOLUME: sei = new SEIContentColourVolume; xParseSEIContentColourVolume((SEIContentColourVolume&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::EQUIRECTANGULAR_PROJECTION: sei = new SEIEquirectangularProjection; xParseSEIEquirectangularProjection((SEIEquirectangularProjection&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::SPHERE_ROTATION: sei = new SEISphereRotation; xParseSEISphereRotation((SEISphereRotation&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::OMNI_VIEWPORT: sei = new SEIOmniViewport; xParseSEIOmniViewport((SEIOmniViewport&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::CUBEMAP_PROJECTION: sei = new SEICubemapProjection; xParseSEICubemapProjection((SEICubemapProjection&)*sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::REGION_WISE_PACKING: sei = new SEIRegionWisePacking; xParseSEIRegionWisePacking((SEIRegionWisePacking&) *sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::ANNOTATED_REGIONS: sei = new SEIAnnotatedRegions; xParseSEIAnnotatedRegions((SEIAnnotatedRegions&)*sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::FISHEYE_VIDEO_INFO: sei = new SEIFisheyeVideoInfo; xParseSEIFisheyeVideoInfo((SEIFisheyeVideoInfo&)*sei, payloadSize, pDecodedMessageOutputStream); break; case SEI::REGIONAL_NESTING: sei = new SEIRegionalNesting; xParseSEIRegionalNesting((SEIRegionalNesting&) *sei, payloadSize, sps, pDecodedMessageOutputStream); break; #if SHUTTER_INTERVAL_SEI_MESSAGE case SEI::SHUTTER_INTERVAL_INFO: sei = new SEIShutterIntervalInfo; xParseSEIShutterInterval((SEIShutterIntervalInfo&)*sei, payloadSize, pDecodedMessageOutputStream); break; #endif #if JCTVC_AD0021_SEI_MANIFEST case SEI::SEI_MANIFEST: sei = new SEIManifest; xParseSEISEIManifest((SEIManifest&)*sei, payloadSize, pDecodedMessageOutputStream); break; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION case SEI::SEI_PREFIX_INDICATION: sei = new SEIPrefixIndication; xParseSEISEIPrefixIndication((SEIPrefixIndication&)*sei, payloadSize, pDecodedMessageOutputStream); break; #endif default: for (UInt i = 0; i < payloadSize; i++) { UInt seiByte; std::string msg = std::string("unknown ")+typeName+std::string(" payload byte"); sei_read_code (NULL, 8, seiByte, msg.c_str()); } printf ("Unknown prefix SEI message (payloadType = %d) was found!\n", payloadType); if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << "Unknown "<< typeName << " message (payloadType = " << payloadType << ") was found!\n"; } break; } } Void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream, const vector& allowedSeiTypes, std::string const &typeName) { #if ENC_DEC_TRACE xTraceSEIHeader(); #endif Int payloadType = 0; UInt val = 0; do { sei_read_code(NULL, 8, val, "payload_type"); payloadType += val; } while (val==0xFF); UInt payloadSize = 0; do { sei_read_code(NULL, 8, val, "payload_size"); payloadSize += val; } while (val==0xFF); #if ENC_DEC_TRACE xTraceSEIMessageType((SEI::PayloadType)payloadType); #endif /* extract the payload for this single SEI message. * This allows greater safety in erroneous parsing of an SEI message * from affecting subsequent messages. * After parsing the payload, bs needs to be restored as the primary * bitstream. */ TComInputBitstream *bs = getBitstream(); setBitstream(bs->extractSubstream(payloadSize * 8)); SEI *sei = NULL; if (std::find(allowedSeiTypes.begin(), allowedSeiTypes.begin(), payloadType) != allowedSeiTypes.end()) { xReadSEIPayloadData(payloadType, payloadSize, sei, nalUnitType, sps, pDecodedMessageOutputStream, typeName); } else { for (UInt i = 0; i < payloadSize; i++) { UInt seiByte; sei_read_code (NULL, 8, seiByte, "unknown SEI payload byte"); } printf ("Unknown SEI message (payloadType = %d) was found!\n", payloadType); if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << "Unknown SEI message (payloadType = " << payloadType << ") was found!\n"; } } if (sei != NULL) { seis.push_back(sei); } /* By definition the underlying bitstream terminates in a byte-aligned manner. * 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data * 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker * 3. Extract the remainingreserved_payload_extension_data bits. * * If there are fewer than 9 bits available, extract them. */ Int payloadBitsRemaining = getBitstream()->getNumBitsLeft(); if (payloadBitsRemaining) /* more_data_in_payload() */ { for (; payloadBitsRemaining > 9; payloadBitsRemaining--) { UInt reservedPayloadExtensionData; sei_read_code ( pDecodedMessageOutputStream, 1, reservedPayloadExtensionData, "reserved_payload_extension_data"); } /* 2 */ Int finalBits = getBitstream()->peekBits(payloadBitsRemaining); Int finalPayloadBits = 0; for (Int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++) { continue; } /* 3 */ for (; payloadBitsRemaining > 9 - finalPayloadBits; payloadBitsRemaining--) { UInt reservedPayloadExtensionData; sei_read_flag ( 0, reservedPayloadExtensionData, "reserved_payload_extension_data"); } UInt dummy; sei_read_flag( 0, dummy, "payload_bit_equal_to_one"); payloadBitsRemaining--; while (payloadBitsRemaining) { sei_read_flag( 0, dummy, "payload_bit_equal_to_zero"); payloadBitsRemaining--; } } /* restore primary bitstream for sei_message */ delete getBitstream(); setBitstream(bs); } Void SEIReader::xParseSEIBufferingPeriod(SEIBufferingPeriod& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream) { Int i, nalOrVcl; UInt code; const TComVUI *pVUI = sps->getVuiParameters(); const TComHRD *pHRD = pVUI->getHrdParameters(); output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_seq_parameter_set_id" ); sei.m_bpSeqParameterSetId = code; if( !pHRD->getSubPicCpbParamsPresentFlag() ) { sei_read_flag( pDecodedMessageOutputStream, code, "irap_cpb_params_present_flag" ); sei.m_rapCpbParamsPresentFlag = code; } if( sei.m_rapCpbParamsPresentFlag ) { sei_read_code( pDecodedMessageOutputStream, pHRD->getCpbRemovalDelayLengthMinus1() + 1, code, "cpb_delay_offset" ); sei.m_cpbDelayOffset = code; sei_read_code( pDecodedMessageOutputStream, pHRD->getDpbOutputDelayLengthMinus1() + 1, code, "dpb_delay_offset" ); sei.m_dpbDelayOffset = code; } //read splicing flag and cpb_removal_delay_delta sei_read_flag( pDecodedMessageOutputStream, code, "concatenation_flag"); sei.m_concatenationFlag = code; sei_read_code( pDecodedMessageOutputStream, ( pHRD->getCpbRemovalDelayLengthMinus1() + 1 ), code, "au_cpb_removal_delay_delta_minus1" ); sei.m_auCpbRemovalDelayDelta = code + 1; for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( pHRD->getNalHrdParametersPresentFlag() ) ) || ( ( nalOrVcl == 1 ) && ( pHRD->getVclHrdParametersPresentFlag() ) ) ) { for( i = 0; i < ( pHRD->getCpbCntMinus1( 0 ) + 1 ); i ++ ) { sei_read_code( pDecodedMessageOutputStream, ( pHRD->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , code, nalOrVcl?"vcl_initial_cpb_removal_delay":"nal_initial_cpb_removal_delay" ); sei.m_initialCpbRemovalDelay[i][nalOrVcl] = code; sei_read_code( pDecodedMessageOutputStream, ( pHRD->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , code, nalOrVcl?"vcl_initial_cpb_removal_offset":"nal_initial_cpb_removal_offset" ); sei.m_initialCpbRemovalDelayOffset[i][nalOrVcl] = code; if( pHRD->getSubPicCpbParamsPresentFlag() || sei.m_rapCpbParamsPresentFlag ) { sei_read_code( pDecodedMessageOutputStream, ( pHRD->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , code, nalOrVcl?"vcl_initial_alt_cpb_removal_delay":"nal_initial_alt_cpb_removal_delay" ); sei.m_initialAltCpbRemovalDelay[i][nalOrVcl] = code; sei_read_code( pDecodedMessageOutputStream, ( pHRD->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , code, nalOrVcl?"vcl_initial_alt_cpb_removal_offset":"nal_initial_alt_cpb_removal_offset" ); sei.m_initialAltCpbRemovalDelayOffset[i][nalOrVcl] = code; } } } } } Void SEIReader::xParseSEIPictureTiming(SEIPictureTiming& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream) { Int i; UInt code; const TComVUI *vui = sps->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); if( vui->getFrameFieldInfoPresentFlag() ) { sei_read_code( pDecodedMessageOutputStream, 4, code, "pic_struct" ); sei.m_picStruct = code; sei_read_code( pDecodedMessageOutputStream, 2, code, "source_scan_type" ); sei.m_sourceScanType = code; sei_read_flag( pDecodedMessageOutputStream, code, "duplicate_flag" ); sei.m_duplicateFlag = (code == 1); } if( hrd->getCpbDpbDelaysPresentFlag()) { sei_read_code( pDecodedMessageOutputStream, ( hrd->getCpbRemovalDelayLengthMinus1() + 1 ), code, "au_cpb_removal_delay_minus1" ); sei.m_auCpbRemovalDelay = code + 1; sei_read_code( pDecodedMessageOutputStream, ( hrd->getDpbOutputDelayLengthMinus1() + 1 ), code, "pic_dpb_output_delay" ); sei.m_picDpbOutputDelay = code; if(hrd->getSubPicCpbParamsPresentFlag()) { sei_read_code( pDecodedMessageOutputStream, hrd->getDpbOutputDelayDuLengthMinus1()+1, code, "pic_dpb_output_du_delay" ); sei.m_picDpbOutputDuDelay = code; } if( hrd->getSubPicCpbParamsPresentFlag() && hrd->getSubPicCpbParamsInPicTimingSEIFlag() ) { sei_read_uvlc( pDecodedMessageOutputStream, code, "num_decoding_units_minus1"); sei.m_numDecodingUnitsMinus1 = code; sei_read_flag( pDecodedMessageOutputStream, code, "du_common_cpb_removal_delay_flag" ); sei.m_duCommonCpbRemovalDelayFlag = code; if( sei.m_duCommonCpbRemovalDelayFlag ) { sei_read_code( pDecodedMessageOutputStream, ( hrd->getDuCpbRemovalDelayLengthMinus1() + 1 ), code, "du_common_cpb_removal_delay_increment_minus1" ); sei.m_duCommonCpbRemovalDelayMinus1 = code; } sei.m_numNalusInDuMinus1.resize(sei.m_numDecodingUnitsMinus1 + 1 ); sei.m_duCpbRemovalDelayMinus1.resize( sei.m_numDecodingUnitsMinus1 + 1 ); for( i = 0; i <= sei.m_numDecodingUnitsMinus1; i ++ ) { sei_read_uvlc( pDecodedMessageOutputStream, code, "num_nalus_in_du_minus1[i]"); sei.m_numNalusInDuMinus1[ i ] = code; if( ( !sei.m_duCommonCpbRemovalDelayFlag ) && ( i < sei.m_numDecodingUnitsMinus1 ) ) { sei_read_code( pDecodedMessageOutputStream, ( hrd->getDuCpbRemovalDelayLengthMinus1() + 1 ), code, "du_cpb_removal_delay_minus1[i]" ); sei.m_duCpbRemovalDelayMinus1[ i ] = code; } } } } } Void SEIReader::xParseSEIPanScanRect(SEIPanScanRect& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, code, "pan_scan_rect_id" ); sei.m_panScanRectId = code; sei_read_flag( pDecodedMessageOutputStream, code, "pan_scan_rect_cancel_flag" ); sei.m_panScanRectCancelFlag = code!=0; if (!sei.m_panScanRectCancelFlag) { UInt numRegions; sei_read_uvlc( pDecodedMessageOutputStream, numRegions, "pan_scan_cnt_minus1" ); numRegions++; sei.m_panScanRectRegions.resize(numRegions); for(UInt region=0; region0); sei_read_code( pDecodedMessageOutputStream, 8, code, "itu_t_t35_country_code" ); payloadSize--; if (code == 255) { assert(payloadSize>0); sei_read_code( pDecodedMessageOutputStream, 8, code, "itu_t_t35_country_code_extension_byte" ); payloadSize--; code+=255; } sei.m_ituCountryCode = code; sei.m_userData.resize(payloadSize); for (UInt i = 0; i < sei.m_userData.size(); i++) { sei_read_code( NULL, 8, code, "itu_t_t35_payload_byte" ); sei.m_userData[i] = code; } if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << " itu_t_t35 payload size: " << sei.m_userData.size() << "\n"; } } Void SEIReader::xParseSEIUserDataUnregistered(SEIUserDataUnregistered &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { assert(payloadSize >= ISO_IEC_11578_LEN); UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); for (UInt i = 0; i < ISO_IEC_11578_LEN; i++) { sei_read_code( pDecodedMessageOutputStream, 8, val, "uuid_iso_iec_11578"); sei.m_uuid_iso_iec_11578[i] = val; } sei.m_userData.resize(payloadSize - ISO_IEC_11578_LEN); for (UInt i = 0; i < sei.m_userData.size(); i++) { sei_read_code( NULL, 8, val, "user_data_payload_byte" ); sei.m_userData[i] = val; } if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << " User data payload size: " << sei.m_userData.size() << "\n"; } } Void SEIReader::xParseSEIRecoveryPoint(SEIRecoveryPoint& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { Int iCode; UInt uiCode; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_svlc( pDecodedMessageOutputStream, iCode, "recovery_poc_cnt" ); sei.m_recoveryPocCnt = iCode; sei_read_flag( pDecodedMessageOutputStream, uiCode, "exact_matching_flag" ); sei.m_exactMatchingFlag = uiCode; sei_read_flag( pDecodedMessageOutputStream, uiCode, "broken_link_flag" ); sei.m_brokenLinkFlag = uiCode; } Void SEIReader::xParseSEISceneInfo(SEISceneInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, code, "scene_info_present_flag" ); sei.m_bSceneInfoPresentFlag = code!=0; if (sei.m_bSceneInfoPresentFlag) { sei_read_flag( pDecodedMessageOutputStream, code, "prev_scene_id_valid_flag" ); sei.m_bPrevSceneIdValidFlag = code!=0; sei_read_uvlc( pDecodedMessageOutputStream, code, "scene_id" ); sei.m_sceneId = code; sei_read_uvlc( pDecodedMessageOutputStream, code, "scene_transition_type" ); sei.m_sceneTransitionType = code; if (sei.m_sceneTransitionType > 3) { sei_read_uvlc( pDecodedMessageOutputStream, code, "second_scene_id" ); sei.m_secondSceneId = code; } else { sei.m_secondSceneId = 0; // set to known value. } } } Void SEIReader::xParseSEIPictureSnapshot(SEIPictureSnapshot& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, code, "snapshot_id" ); sei.m_snapshotId = code; } Void SEIReader::xParseSEIProgressiveRefinementSegmentStart(SEIProgressiveRefinementSegmentStart& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, code, "progressive_refinement_id" ); sei.m_progressiveRefinementId = code; sei_read_uvlc( pDecodedMessageOutputStream, code, "pic_order_cnt_delta" ); sei.m_picOrderCntDelta = code; } Void SEIReader::xParseSEIProgressiveRefinementSegmentEnd(SEIProgressiveRefinementSegmentEnd& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, code, "progressive_refinement_id" ); sei.m_progressiveRefinementId = code; } Void SEIReader::xParseSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, code, "film_grain_characteristics_cancel_flag" ); sei.m_filmGrainCharacteristicsCancelFlag = code!=0; if (!sei.m_filmGrainCharacteristicsCancelFlag) { sei_read_code( pDecodedMessageOutputStream, 2, code, "film_grain_model_id" ); sei.m_filmGrainModelId = code; sei_read_flag( pDecodedMessageOutputStream, code, "separate_colour_description_present_flag" ); sei.m_separateColourDescriptionPresentFlag = code!=0; if (sei.m_separateColourDescriptionPresentFlag) { sei_read_code( pDecodedMessageOutputStream, 3, code, "film_grain_bit_depth_luma_minus8" ); sei.m_filmGrainBitDepthLumaMinus8 = code; sei_read_code( pDecodedMessageOutputStream, 3, code, "film_grain_bit_depth_chroma_minus8" ); sei.m_filmGrainBitDepthChromaMinus8 = code; sei_read_flag( pDecodedMessageOutputStream, code, "film_grain_full_range_flag" ); sei.m_filmGrainFullRangeFlag = code!=0; sei_read_code( pDecodedMessageOutputStream, 8, code, "film_grain_colour_primaries" ); sei.m_filmGrainColourPrimaries = code; sei_read_code( pDecodedMessageOutputStream, 8, code, "film_grain_transfer_characteristics" ); sei.m_filmGrainTransferCharacteristics = code; sei_read_code( pDecodedMessageOutputStream, 8, code, "film_grain_matrix_coeffs" ); sei.m_filmGrainMatrixCoeffs = code; } sei_read_code( pDecodedMessageOutputStream, 2, code, "blending_mode_id" ); sei.m_blendingModeId = code; sei_read_code( pDecodedMessageOutputStream, 4, code, "log2_scale_factor" ); sei.m_log2ScaleFactor = code; for(Int c=0; c<3; c++) { sei_read_flag( pDecodedMessageOutputStream, code, "comp_model_present_flag[c]" ); sei.m_compModel[c].bPresentFlag = code!=0; } for(Int c=0; c<3; c++) { SEIFilmGrainCharacteristics::CompModel &cm=sei.m_compModel[c]; if (cm.bPresentFlag) { #if JVET_X0048_X0103_FILM_GRAIN sei_read_code( pDecodedMessageOutputStream, 8, code, "num_intensity_intervals_minus1[c]"); cm.numIntensityIntervals = code + 1; #else UInt numIntensityIntervals; sei_read_code( pDecodedMessageOutputStream, 8, code, "num_intensity_intervals_minus1[c]" ); numIntensityIntervals = code+1; #endif sei_read_code( pDecodedMessageOutputStream, 3, code, "num_model_values_minus1[c]" ); cm.numModelValues = code+1; #if JVET_X0048_X0103_FILM_GRAIN cm.intensityValues.resize(cm.numIntensityIntervals); for (UInt interval = 0; interval < cm.numIntensityIntervals; interval++) #else cm.intensityValues.resize(numIntensityIntervals); for(UInt interval=0; intervalgetChromaFormatIdc() == CHROMA_400); const UInt numChromaChannels = sei.m_bIsMonochrome ? 1:3; sei.m_filterHintValues.resize(numChromaChannels * sei.m_filterHintSizeX * sei.m_filterHintSizeY); for(std::size_t i=0; i> 3 ) << 3), val, "start_of_coded_interval[i]" ); sei.m_startOfCodedInterval[i] = val; } sei.m_startOfCodedInterval[num] = 1u << sei.m_codedDataBitDepth; break; } case 3: { sei_read_code( pDecodedMessageOutputStream, 16, val, "num_pivots" ); sei.m_numPivots = val; sei.m_codedPivotValue.resize(sei.m_numPivots); sei.m_targetPivotValue.resize(sei.m_numPivots); for(i = 0; i < sei.m_numPivots; i++ ) { sei_read_code( pDecodedMessageOutputStream, ((( sei.m_codedDataBitDepth + 7 ) >> 3 ) << 3), val, "coded_pivot_value[i]" ); sei.m_codedPivotValue[i] = val; sei_read_code( pDecodedMessageOutputStream, ((( sei.m_targetBitDepth + 7 ) >> 3 ) << 3), val, "target_pivot_value[i]" ); sei.m_targetPivotValue[i] = val; } break; } case 4: { sei_read_code( pDecodedMessageOutputStream, 8, val, "camera_iso_speed_idc" ); sei.m_cameraIsoSpeedIdc = val; if( sei.m_cameraIsoSpeedIdc == 255) //Extended_ISO { sei_read_code( pDecodedMessageOutputStream, 32, val, "camera_iso_speed_value" ); sei.m_cameraIsoSpeedValue = val; } sei_read_code( pDecodedMessageOutputStream, 8, val, "exposure_index_idc" ); sei.m_exposureIndexIdc = val; if( sei.m_exposureIndexIdc == 255) //Extended_ISO { sei_read_code( pDecodedMessageOutputStream, 32, val, "exposure_index_value" ); sei.m_exposureIndexValue = val; } sei_read_flag( pDecodedMessageOutputStream, val, "exposure_compensation_value_sign_flag" ); sei.m_exposureCompensationValueSignFlag = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "exposure_compensation_value_numerator" ); sei.m_exposureCompensationValueNumerator = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "exposure_compensation_value_denom_idc" ); sei.m_exposureCompensationValueDenomIdc = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "ref_screen_luminance_white" ); sei.m_refScreenLuminanceWhite = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "extended_range_white_level" ); sei.m_extendedRangeWhiteLevel = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "nominal_black_level_code_value" ); sei.m_nominalBlackLevelLumaCodeValue = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "nominal_white_level_code_value" ); sei.m_nominalWhiteLevelLumaCodeValue= val; sei_read_code( pDecodedMessageOutputStream, 16, val, "extended_white_level_code_value" ); sei.m_extendedWhiteLevelLumaCodeValue = val; break; } default: { assert(!"Undefined SEIToneMapModelId"); break; } }//switch model id }// if(!sei.m_toneMapCancelFlag) } Void SEIReader::xParseSEIFramePacking(SEIFramePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, val, "frame_packing_arrangement_id" ); sei.m_arrangementId = val; sei_read_flag( pDecodedMessageOutputStream, val, "frame_packing_arrangement_cancel_flag" ); sei.m_arrangementCancelFlag = val; if ( !sei.m_arrangementCancelFlag ) { sei_read_code( pDecodedMessageOutputStream, 7, val, "frame_packing_arrangement_type" ); sei.m_arrangementType = val; assert((sei.m_arrangementType > 2) && (sei.m_arrangementType < 6) ); sei_read_flag( pDecodedMessageOutputStream, val, "quincunx_sampling_flag" ); sei.m_quincunxSamplingFlag = val; sei_read_code( pDecodedMessageOutputStream, 6, val, "content_interpretation_type" ); sei.m_contentInterpretationType = val; sei_read_flag( pDecodedMessageOutputStream, val, "spatial_flipping_flag" ); sei.m_spatialFlippingFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "frame0_flipped_flag" ); sei.m_frame0FlippedFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "field_views_flag" ); sei.m_fieldViewsFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "current_frame_is_frame0_flag" ); sei.m_currentFrameIsFrame0Flag = val; sei_read_flag( pDecodedMessageOutputStream, val, "frame0_self_contained_flag" ); sei.m_frame0SelfContainedFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "frame1_self_contained_flag" ); sei.m_frame1SelfContainedFlag = val; if ( sei.m_quincunxSamplingFlag == 0 && sei.m_arrangementType != 5) { sei_read_code( pDecodedMessageOutputStream, 4, val, "frame0_grid_position_x" ); sei.m_frame0GridPositionX = val; sei_read_code( pDecodedMessageOutputStream, 4, val, "frame0_grid_position_y" ); sei.m_frame0GridPositionY = val; sei_read_code( pDecodedMessageOutputStream, 4, val, "frame1_grid_position_x" ); sei.m_frame1GridPositionX = val; sei_read_code( pDecodedMessageOutputStream, 4, val, "frame1_grid_position_y" ); sei.m_frame1GridPositionY = val; } sei_read_code( pDecodedMessageOutputStream, 8, val, "frame_packing_arrangement_reserved_byte" ); sei.m_arrangementReservedByte = val; sei_read_flag( pDecodedMessageOutputStream, val, "frame_packing_arrangement_persistence_flag" ); sei.m_arrangementPersistenceFlag = (val != 0); } sei_read_flag( pDecodedMessageOutputStream, val, "upsampled_aspect_ratio_flag" ); sei.m_upsampledAspectRatio = val; } Void SEIReader::xParseSEIDisplayOrientation(SEIDisplayOrientation& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "display_orientation_cancel_flag" ); sei.cancelFlag = val; if( !sei.cancelFlag ) { sei_read_flag( pDecodedMessageOutputStream, val, "hor_flip" ); sei.horFlip = val; sei_read_flag( pDecodedMessageOutputStream, val, "ver_flip" ); sei.verFlip = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "anticlockwise_rotation" ); sei.anticlockwiseRotation = val; sei_read_flag( pDecodedMessageOutputStream, val, "display_orientation_persistence_flag" ); sei.persistenceFlag = val; } } Void SEIReader::xParseSEIGreenMetadataInfo(SEIGreenMetadataInfo& sei, UInt payloadSize, ostream* pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code(pDecodedMessageOutputStream, 8, code, "green_metadata_type"); sei.m_greenMetadataType = code; sei_read_code(pDecodedMessageOutputStream, 8, code, "xsd_metric_type"); sei.m_xsdMetricType = code; sei_read_code(pDecodedMessageOutputStream, 16, code, "xsd_metric_value"); sei.m_xsdMetricValue = code; } Void SEIReader::xParseSEISOPDescription(SEISOPDescription &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { Int iCode; UInt uiCode; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "sop_seq_parameter_set_id" ); sei.m_sopSeqParameterSetId = uiCode; sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "num_pics_in_sop_minus1" ); sei.m_numPicsInSopMinus1 = uiCode; for (UInt i = 0; i <= sei.m_numPicsInSopMinus1; i++) { sei_read_code( pDecodedMessageOutputStream, 6, uiCode, "sop_vcl_nut[i]" ); sei.m_sopDescVclNaluType[i] = uiCode; sei_read_code( pDecodedMessageOutputStream, 3, sei.m_sopDescTemporalId[i], "sop_temporal_id[i]" ); sei.m_sopDescTemporalId[i] = uiCode; if (sei.m_sopDescVclNaluType[i] != NAL_UNIT_CODED_SLICE_IDR_W_RADL && sei.m_sopDescVclNaluType[i] != NAL_UNIT_CODED_SLICE_IDR_N_LP) { sei_read_uvlc( pDecodedMessageOutputStream, sei.m_sopDescStRpsIdx[i], "sop_short_term_rps_idx[i]" ); sei.m_sopDescStRpsIdx[i] = uiCode; } if (i > 0) { sei_read_svlc( pDecodedMessageOutputStream, iCode, "sop_poc_delta[i]" ); sei.m_sopDescPocDelta[i] = iCode; } } } Void SEIReader::xParseSEIActiveParameterSets(SEIActiveParameterSets& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 4, val, "active_video_parameter_set_id"); sei.activeVPSId = val; sei_read_flag( pDecodedMessageOutputStream, val, "self_contained_cvs_flag"); sei.m_selfContainedCvsFlag = (val != 0); sei_read_flag( pDecodedMessageOutputStream, val, "no_parameter_set_update_flag"); sei.m_noParameterSetUpdateFlag = (val != 0); sei_read_uvlc( pDecodedMessageOutputStream, val, "num_sps_ids_minus1"); sei.numSpsIdsMinus1 = val; sei.activeSeqParameterSetId.resize(sei.numSpsIdsMinus1 + 1); for (Int i=0; i < (sei.numSpsIdsMinus1 + 1); i++) { sei_read_uvlc( pDecodedMessageOutputStream, val, "active_seq_parameter_set_id[i]"); sei.activeSeqParameterSetId[i] = val; } } Void SEIReader::xParseSEIDecodingUnitInfo(SEIDecodingUnitInfo& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, val, "decoding_unit_idx"); sei.m_decodingUnitIdx = val; const TComVUI *vui = sps->getVuiParameters(); if(vui->getHrdParameters()->getSubPicCpbParamsInPicTimingSEIFlag()) { sei_read_code( pDecodedMessageOutputStream, ( vui->getHrdParameters()->getDuCpbRemovalDelayLengthMinus1() + 1 ), val, "du_spt_cpb_removal_delay_increment"); sei.m_duSptCpbRemovalDelay = val; } else { sei.m_duSptCpbRemovalDelay = 0; } sei_read_flag( pDecodedMessageOutputStream, val, "dpb_output_du_delay_present_flag"); sei.m_dpbOutputDuDelayPresentFlag = (val != 0); if(sei.m_dpbOutputDuDelayPresentFlag) { sei_read_code( pDecodedMessageOutputStream, vui->getHrdParameters()->getDpbOutputDelayDuLengthMinus1() + 1, val, "pic_spt_dpb_output_du_delay"); sei.m_picSptDpbOutputDuDelay = val; } } Void SEIReader::xParseSEITemporalLevel0Index(SEITemporalLevel0Index& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 8, val, "temporal_sub_layer_zero_idx" ); sei.tl0Idx = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "irap_pic_id" ); sei.rapIdx = val; } Void SEIReader::xParseSEIDecodedPictureHash(SEIDecodedPictureHash& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt bytesRead = 0; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt val; sei_read_code( pDecodedMessageOutputStream, 8, val, "hash_type"); sei.method = static_cast(val); bytesRead++; const TChar *traceString="\0"; switch (sei.method) { case HASHTYPE_MD5: traceString="picture_md5"; break; case HASHTYPE_CRC: traceString="picture_crc"; break; case HASHTYPE_CHECKSUM: traceString="picture_checksum"; break; default: assert(false); break; } if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << " " << std::setw(55) << traceString << ": " << std::hex << std::setfill('0'); } sei.m_pictureHash.hash.clear(); for(;bytesRead < payloadSize; bytesRead++) { sei_read_code( NULL, 8, val, traceString); sei.m_pictureHash.hash.push_back((UChar)val); if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << std::setw(2) << val; } } if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << std::dec << std::setfill(' ') << "\n"; } } Void SEIReader::xParseSEIScalableNesting(SEIScalableNesting& sei, const NalUnitType nalUnitType, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream) { UInt uiCode; SEIMessages seis; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, uiCode, "bitstream_subset_flag" ); sei.m_bitStreamSubsetFlag = uiCode; sei_read_flag( pDecodedMessageOutputStream, uiCode, "nesting_op_flag" ); sei.m_nestingOpFlag = uiCode; if (sei.m_nestingOpFlag) { sei_read_flag( pDecodedMessageOutputStream, uiCode, "default_op_flag" ); sei.m_defaultOpFlag = uiCode; sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "nesting_num_ops_minus1" ); sei.m_nestingNumOpsMinus1 = uiCode; for (UInt i = sei.m_defaultOpFlag; i <= sei.m_nestingNumOpsMinus1; i++) { sei_read_code( pDecodedMessageOutputStream, 3, uiCode, "nesting_max_temporal_id_plus1[i]" ); sei.m_nestingMaxTemporalIdPlus1[i] = uiCode; sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "nesting_op_idx[i]" ); sei.m_nestingOpIdx[i] = uiCode; } } else { sei_read_flag( pDecodedMessageOutputStream, uiCode, "all_layers_flag" ); sei.m_allLayersFlag = uiCode; if (!sei.m_allLayersFlag) { sei_read_code( pDecodedMessageOutputStream, 3, uiCode, "nesting_no_op_max_temporal_id_plus1" ); sei.m_nestingNoOpMaxTemporalIdPlus1 = uiCode; sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "nesting_num_layers_minus1" ); sei.m_nestingNumLayersMinus1 = uiCode; for (UInt i = 0; i <= sei.m_nestingNumLayersMinus1; i++) { sei_read_code( pDecodedMessageOutputStream, 6, uiCode, "nesting_layer_id[i]" ); sei.m_nestingLayerId[i] = uiCode; } } } // byte alignment while ( m_pcBitstream->getNumBitsRead() % 8 != 0 ) { UInt code; sei_read_flag( pDecodedMessageOutputStream, code, "nesting_zero_bit" ); } // read nested SEI messages do { if(nalUnitType == NAL_UNIT_PREFIX_SEI) { xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps, pDecodedMessageOutputStream, SEI::prefix_sei_messages, std::string("scalable nested SEI")); } else { xReadSEImessage(sei.m_nestedSEIs, nalUnitType, sps, pDecodedMessageOutputStream, SEI::suffix_sei_messages, std::string("scalable nested SEI")); } } while (m_pcBitstream->getNumBitsLeft() > 8); if (pDecodedMessageOutputStream) { (*pDecodedMessageOutputStream) << "End of scalable nesting SEI message\n"; } } Void SEIReader::xParseSEIRegionRefreshInfo(SEIRegionRefreshInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "refreshed_region_flag" ); sei.m_gdrForegroundFlag = val ? 1 : 0; } Void SEIReader::xParseSEINoDisplay(SEINoDisplay& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei.m_noDisplay = true; } Void SEIReader::xParseSEITimeCode(SEITimeCode& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 2, code, "num_clock_ts"); sei.numClockTs = code; for(Int i = 0; i < sei.numClockTs; i++) { TComSEITimeSet currentTimeSet; sei_read_flag( pDecodedMessageOutputStream, code, "clock_time_stamp_flag[i]"); currentTimeSet.clockTimeStampFlag = code; if(currentTimeSet.clockTimeStampFlag) { sei_read_flag( pDecodedMessageOutputStream, code, "nuit_field_based_flag"); currentTimeSet.numUnitFieldBasedFlag = code; sei_read_code( pDecodedMessageOutputStream, 5, code, "counting_type"); currentTimeSet.countingType = code; sei_read_flag( pDecodedMessageOutputStream, code, "full_timestamp_flag"); currentTimeSet.fullTimeStampFlag = code; sei_read_flag( pDecodedMessageOutputStream, code, "discontinuity_flag"); currentTimeSet.discontinuityFlag = code; sei_read_flag( pDecodedMessageOutputStream, code, "cnt_dropped_flag"); currentTimeSet.cntDroppedFlag = code; sei_read_code( pDecodedMessageOutputStream, 9, code, "n_frames"); currentTimeSet.numberOfFrames = code; if(currentTimeSet.fullTimeStampFlag) { sei_read_code( pDecodedMessageOutputStream, 6, code, "seconds_value"); currentTimeSet.secondsValue = code; sei_read_code( pDecodedMessageOutputStream, 6, code, "minutes_value"); currentTimeSet.minutesValue = code; sei_read_code( pDecodedMessageOutputStream, 5, code, "hours_value"); currentTimeSet.hoursValue = code; } else { sei_read_flag( pDecodedMessageOutputStream, code, "seconds_flag"); currentTimeSet.secondsFlag = code; if(currentTimeSet.secondsFlag) { sei_read_code( pDecodedMessageOutputStream, 6, code, "seconds_value"); currentTimeSet.secondsValue = code; sei_read_flag( pDecodedMessageOutputStream, code, "minutes_flag"); currentTimeSet.minutesFlag = code; if(currentTimeSet.minutesFlag) { sei_read_code( pDecodedMessageOutputStream, 6, code, "minutes_value"); currentTimeSet.minutesValue = code; sei_read_flag( pDecodedMessageOutputStream, code, "hours_flag"); currentTimeSet.hoursFlag = code; if(currentTimeSet.hoursFlag) { sei_read_code( pDecodedMessageOutputStream, 5, code, "hours_value"); currentTimeSet.hoursValue = code; } } } } sei_read_code( pDecodedMessageOutputStream, 5, code, "time_offset_length"); currentTimeSet.timeOffsetLength = code; if(currentTimeSet.timeOffsetLength > 0) { sei_read_code( pDecodedMessageOutputStream, currentTimeSet.timeOffsetLength, code, "time_offset_value"); if((code & (1 << (currentTimeSet.timeOffsetLength-1))) == 0) { currentTimeSet.timeOffsetValue = code; } else { code &= (1<< (currentTimeSet.timeOffsetLength-1)) - 1; currentTimeSet.timeOffsetValue = ~code + 1; } } } sei.timeSetArray[i] = currentTimeSet; } } Void SEIReader::xParseSEIMasteringDisplayColourVolume(SEIMasteringDisplayColourVolume& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[0]" ); sei.values.primaries[0][0] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[0]" ); sei.values.primaries[0][1] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[1]" ); sei.values.primaries[1][0] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[1]" ); sei.values.primaries[1][1] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[2]" ); sei.values.primaries[2][0] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[2]" ); sei.values.primaries[2][1] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "white_point_x" ); sei.values.whitePoint[0] = code; sei_read_code( pDecodedMessageOutputStream, 16, code, "white_point_y" ); sei.values.whitePoint[1] = code; sei_read_code( pDecodedMessageOutputStream, 32, code, "max_display_mastering_luminance" ); sei.values.maxLuminance = code; sei_read_code( pDecodedMessageOutputStream, 32, code, "min_display_mastering_luminance" ); sei.values.minLuminance = code; } Void SEIReader::xParseSEISegmentedRectFramePacking(SEISegmentedRectFramePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "segmented_rect_frame_packing_arrangement_cancel_flag" ); sei.m_arrangementCancelFlag = val; if( !sei.m_arrangementCancelFlag ) { sei_read_code( pDecodedMessageOutputStream, 2, val, "segmented_rect_content_interpretation_type" ); sei.m_contentInterpretationType = val; sei_read_flag( pDecodedMessageOutputStream, val, "segmented_rect_frame_packing_arrangement_persistence" ); sei.m_arrangementPersistenceFlag = val; } } Void SEIReader::xParseSEITempMotionConstraintsTileSets(SEITempMotionConstrainedTileSets& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, code, "mc_all_tiles_exact_sample_value_match_flag"); sei.m_mc_all_tiles_exact_sample_value_match_flag = (code != 0); sei_read_flag( pDecodedMessageOutputStream, code, "each_tile_one_tile_set_flag"); sei.m_each_tile_one_tile_set_flag = (code != 0); if(!sei.m_each_tile_one_tile_set_flag) { sei_read_flag( pDecodedMessageOutputStream, code, "limited_tile_set_display_flag"); sei.m_limited_tile_set_display_flag = (code != 0); sei_read_uvlc( pDecodedMessageOutputStream, code, "num_sets_in_message_minus1"); sei.setNumberOfTileSets(code + 1); if(sei.getNumberOfTileSets() != 0) { for(Int i = 0; i < sei.getNumberOfTileSets(); i++) { sei_read_uvlc( pDecodedMessageOutputStream, code, "mcts_id"); sei.tileSetData(i).m_mcts_id = code; if(sei.m_limited_tile_set_display_flag) { sei_read_flag( pDecodedMessageOutputStream, code, "display_tile_set_flag"); sei.tileSetData(i).m_display_tile_set_flag = (code != 1); } sei_read_uvlc( pDecodedMessageOutputStream, code, "num_tile_rects_in_set_minus1"); sei.tileSetData(i).setNumberOfTileRects(code + 1); for(Int j=0; jgetNumBitsRead() % 8 != 0) { sei_read_flag(pDecodedMessageOutputStream, code, "mcts_alignment_bit_equal_to_zero"); } for (Int j = 0; j < EIS.m_vpsRbspData.size(); j++) { EIS.m_vpsRbspData[j].resize(EIS.m_vpsRbspDataLength[j]); for (Int k = 0; k < EIS.m_vpsRbspDataLength[j]; k++) { sei_read_code(pDecodedMessageOutputStream, 8, code, "vps_rbsp_data_byte[ i ][ j ][ k ]"); EIS.m_vpsRbspData[j][k] = code; } } for (Int j = 0; j < EIS.m_spsRbspData.size(); j++) { EIS.m_spsRbspData[j].resize(EIS.m_spsRbspDataLength[j]); for (Int k = 0; k < EIS.m_spsRbspDataLength[j]; k++) { sei_read_code(pDecodedMessageOutputStream, 8, code, "sps_rbsp_data_byte[ i ][ j ][ k ]"); EIS.m_spsRbspData[j][k] = code; } } for (Int j = 0; j < EIS.m_ppsRbspData.size(); j++) { EIS.m_ppsRbspData[j].resize(EIS.m_ppsRbspDataLength[j]); for (Int k = 0; k < EIS.m_ppsRbspDataLength[j]; k++) { sei_read_code(pDecodedMessageOutputStream, 8, code, "pps_rbsp_data_byte[ i ][ j ][ k ]"); EIS.m_ppsRbspData[j][k] = code; } } sei.m_MCTSExtractionInfoSets.push_back(EIS); } } #endif Void SEIReader::xParseSEIChromaResamplingFilterHint(SEIChromaResamplingFilterHint& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt uiCode; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 8, uiCode, "ver_chroma_filter_idc"); sei.m_verChromaFilterIdc = uiCode; sei_read_code( pDecodedMessageOutputStream, 8, uiCode, "hor_chroma_filter_idc"); sei.m_horChromaFilterIdc = uiCode; sei_read_flag( pDecodedMessageOutputStream, uiCode, "ver_filtering_field_processing_flag"); sei.m_verFilteringFieldProcessingFlag = uiCode; if(sei.m_verChromaFilterIdc == 1 || sei.m_horChromaFilterIdc == 1) { sei_read_uvlc( pDecodedMessageOutputStream, uiCode, "target_format_idc"); sei.m_targetFormatIdc = uiCode; if(sei.m_verChromaFilterIdc == 1) { UInt numVerticalFilters; sei_read_uvlc( pDecodedMessageOutputStream, numVerticalFilters, "num_vertical_filters"); sei.m_verFilterCoeff.resize(numVerticalFilters); if(numVerticalFilters > 0) { for(Int i = 0; i < numVerticalFilters; i++) { UInt verTapLengthMinus1; sei_read_uvlc( pDecodedMessageOutputStream, verTapLengthMinus1, "ver_tap_length_minus_1"); sei.m_verFilterCoeff[i].resize(verTapLengthMinus1+1); for(Int j = 0; j < (verTapLengthMinus1 + 1); j++) { sei_read_svlc( pDecodedMessageOutputStream, sei.m_verFilterCoeff[i][j], "ver_filter_coeff"); } } } } if(sei.m_horChromaFilterIdc == 1) { UInt numHorizontalFilters; sei_read_uvlc( pDecodedMessageOutputStream, numHorizontalFilters, "num_horizontal_filters"); sei.m_horFilterCoeff.resize(numHorizontalFilters); if(numHorizontalFilters > 0) { for(Int i = 0; i < numHorizontalFilters; i++) { UInt horTapLengthMinus1; sei_read_uvlc( pDecodedMessageOutputStream, horTapLengthMinus1, "hor_tap_length_minus_1"); sei.m_horFilterCoeff[i].resize(horTapLengthMinus1+1); for(Int j = 0; j < (horTapLengthMinus1 + 1); j++) { sei_read_svlc( pDecodedMessageOutputStream, sei.m_horFilterCoeff[i][j], "hor_filter_coeff"); } } } } } } Void SEIReader::xParseSEIKneeFunctionInfo(SEIKneeFunctionInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { Int i; UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, val, "knee_function_id" ); sei.m_kneeId = val; sei_read_flag( pDecodedMessageOutputStream, val, "knee_function_cancel_flag" ); sei.m_kneeCancelFlag = val; if ( !sei.m_kneeCancelFlag ) { sei_read_flag( pDecodedMessageOutputStream, val, "knee_function_persistence_flag" ); sei.m_kneePersistenceFlag = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "input_d_range" ); sei.m_kneeInputDrange = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "input_disp_luminance" ); sei.m_kneeInputDispLuminance = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "output_d_range" ); sei.m_kneeOutputDrange = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "output_disp_luminance" ); sei.m_kneeOutputDispLuminance = val; sei_read_uvlc( pDecodedMessageOutputStream, val, "num_knee_points_minus1" ); sei.m_kneeNumKneePointsMinus1 = val; assert( sei.m_kneeNumKneePointsMinus1 > 0 ); sei.m_kneeInputKneePoint.resize(sei.m_kneeNumKneePointsMinus1+1); sei.m_kneeOutputKneePoint.resize(sei.m_kneeNumKneePointsMinus1+1); for(i = 0; i <= sei.m_kneeNumKneePointsMinus1; i++ ) { sei_read_code( pDecodedMessageOutputStream, 10, val, "input_knee_point" ); sei.m_kneeInputKneePoint[i] = val; sei_read_code( pDecodedMessageOutputStream, 10, val, "output_knee_point" ); sei.m_kneeOutputKneePoint[i] = val; } } } Void SEIReader::xParseSEIContentColourVolume(SEIContentColourVolume& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { Int i; UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "ccv_cancel_flag" ); sei.m_ccvCancelFlag = val; if ( !sei.m_ccvCancelFlag ) { Int iVal; sei_read_flag( pDecodedMessageOutputStream, val, "ccv_persistence_flag" ); sei.m_ccvPersistenceFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "ccv_primaries_present_flag" ); sei.m_ccvPrimariesPresentFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "ccv_min_luminance_value_present_flag" ); sei.m_ccvMinLuminanceValuePresentFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "ccv_max_luminance_value_present_flag" ); sei.m_ccvMaxLuminanceValuePresentFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "ccv_avg_luminance_value_present_flag" ); sei.m_ccvAvgLuminanceValuePresentFlag = val; if (sei.m_ccvPrimariesPresentFlag) { for (i = 0; i < MAX_NUM_COMPONENT; i++) { sei_read_scode( pDecodedMessageOutputStream, 32, iVal, "ccv_primaries_x[i]" ); sei.m_ccvPrimariesX[i] = iVal; sei_read_scode( pDecodedMessageOutputStream, 32, iVal, "ccv_primaries_y[i]" ); sei.m_ccvPrimariesY[i] = iVal; } } if (sei.m_ccvMinLuminanceValuePresentFlag) { sei_read_code( pDecodedMessageOutputStream, 32, val, "ccv_min_luminance_value" ); sei.m_ccvMinLuminanceValue = val; } if (sei.m_ccvMaxLuminanceValuePresentFlag) { sei_read_code( pDecodedMessageOutputStream, 32, val, "ccv_max_luminance_value" ); sei.m_ccvMaxLuminanceValue = val; } if (sei.m_ccvAvgLuminanceValuePresentFlag) { sei_read_code( pDecodedMessageOutputStream, 32, val, "ccv_avg_luminance_value" ); sei.m_ccvAvgLuminanceValue = val; } } } #if SHUTTER_INTERVAL_SEI_MESSAGE Void SEIReader::xParseSEIShutterInterval(SEIShutterIntervalInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { Int i; UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_time_scale"); sei.m_siiTimeScale = val; sei_read_flag(pDecodedMessageOutputStream, val, "fixed_shutter_interval_within_clvs_flag"); sei.m_siiFixedSIwithinCLVS = val; if (sei.m_siiFixedSIwithinCLVS) { sei_read_code(pDecodedMessageOutputStream, 32, val, "sii_num_units_in_shutter_interval"); sei.m_siiNumUnitsInShutterInterval = val; } else { sei_read_code(pDecodedMessageOutputStream, 3, val, "sii_max_sub_layers_minus1 "); sei.m_siiMaxSubLayersMinus1 = val; sei.m_siiSubLayerNumUnitsInSI.resize(sei.m_siiMaxSubLayersMinus1 + 1); for (i = 0; i <= sei.m_siiMaxSubLayersMinus1; i++) { sei_read_code(pDecodedMessageOutputStream, 32, val, "sub_layer_num_units_in_shutter_interval[ i ]"); sei.m_siiSubLayerNumUnitsInSI[i] = val; } } } #endif Void SEIReader::xParseSEIEquirectangularProjection(SEIEquirectangularProjection& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "erp_cancel_flag" ); sei.m_erpCancelFlag = val; if( !sei.m_erpCancelFlag ) { sei_read_flag( pDecodedMessageOutputStream, val, "erp_persistence_flag" ); sei.m_erpPersistenceFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "erp_guard_band_flag" ); sei.m_erpGuardBandFlag = val; sei_read_code( pDecodedMessageOutputStream, 2, val, "erp_reserved_zero_2bits" ); if ( sei.m_erpGuardBandFlag == 1) { sei_read_code( pDecodedMessageOutputStream, 3, val, "erp_guard_band_type" ); sei.m_erpGuardBandType = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "erp_left_guard_band_width" ); sei.m_erpLeftGuardBandWidth = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "erp_right_guard_band_width"); sei.m_erpRightGuardBandWidth = val; } } } Void SEIReader::xParseSEISphereRotation(SEISphereRotation& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; Int sval; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag( pDecodedMessageOutputStream, val, "sphere_rotation_cancel_flag" ); sei.m_sphereRotationCancelFlag = val; if( !sei.m_sphereRotationCancelFlag ) { sei_read_flag ( pDecodedMessageOutputStream, val, "sphere_rotation_persistence_flag" ); sei.m_sphereRotationPersistenceFlag = val; sei_read_code ( pDecodedMessageOutputStream, 6, val, "sphere_rotation_reserved_zero_6bits" ); sei_read_scode( pDecodedMessageOutputStream, 32, sval, "sphere_rotation_yaw" ); sei.m_sphereRotationYaw = sval; sei_read_scode( pDecodedMessageOutputStream, 32, sval, "sphere_rotation_pitch" ); sei.m_sphereRotationPitch = sval; sei_read_scode( pDecodedMessageOutputStream, 32, sval, "sphere_rotation_roll" ); sei.m_sphereRotationRoll = sval; } } Void SEIReader::xParseSEIOmniViewport(SEIOmniViewport& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt code; Int scode; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code( pDecodedMessageOutputStream, 10, code, "omni_viewport_id" ); sei.m_omniViewportId = code; sei_read_flag( pDecodedMessageOutputStream, code, "omni_viewport_cancel_flag" ); sei.m_omniViewportCancelFlag = code; if (!sei.m_omniViewportCancelFlag) { UInt numRegions; sei_read_flag( pDecodedMessageOutputStream, code, "omni_viewport_persistence_flag" ); sei.m_omniViewportPersistenceFlag = code; sei_read_code( pDecodedMessageOutputStream, 4, numRegions, "omni_viewport_cnt_minus1" ); numRegions++; sei.m_omniViewportRegions.resize(numRegions); for(UInt region=0; regiongetNumBitsRead() % 8 != 0) { UInt code; sei_read_flag(pDecodedMessageOutputStream, code, "ar_bit_equal_to_zero"); } sei.m_hdr.m_annotatedRegionsObjectLabelLang.clear(); do { sei_read_code(pDecodedMessageOutputStream, 8, val, "ar_label_language"); if (val) { assert(sei.m_hdr.m_annotatedRegionsObjectLabelLang.size()<256); sei.m_hdr.m_annotatedRegionsObjectLabelLang.push_back((char)val); } } while (val != '\0'); } UInt numLabelUpdates; sei_read_uvlc(pDecodedMessageOutputStream, numLabelUpdates, "ar_num_label_updates"); assert(numLabelUpdates<256); sei.m_annotatedLabels.clear(); sei.m_annotatedLabels.resize(numLabelUpdates); for (auto it=sei.m_annotatedLabels.begin(); it!=sei.m_annotatedLabels.end(); it++) { SEIAnnotatedRegions::AnnotatedRegionLabel &ar = it->second; sei_read_uvlc(pDecodedMessageOutputStream, val, "ar_label_idx[]"); it->first = val; assert(val<256); sei_read_flag(pDecodedMessageOutputStream, val, "ar_label_cancel_flag"); ar.labelValid = !val; if (ar.labelValid) { ar.label.clear(); // byte alignment while (m_pcBitstream->getNumBitsRead() % 8 != 0) { UInt code; sei_read_flag(pDecodedMessageOutputStream, code, "ar_bit_equal_to_zero"); } do { sei_read_code(pDecodedMessageOutputStream, 8, val, "ar_label[]"); if (val) { assert(ar.label.size()<256); ar.label.push_back((char)val); } } while (val != '\0'); } } } UInt numObjUpdates; sei_read_uvlc(pDecodedMessageOutputStream, numObjUpdates, "ar_num_object_updates"); assert(numObjUpdates<256); sei.m_annotatedRegions.clear(); sei.m_annotatedRegions.resize(numObjUpdates); for (auto it=sei.m_annotatedRegions.begin(); it!=sei.m_annotatedRegions.end(); it++) { sei_read_uvlc(pDecodedMessageOutputStream, val, "ar_object_idx"); it->first=val; assert(val<256); SEIAnnotatedRegions::AnnotatedRegionObject &ar = it->second; sei_read_flag(pDecodedMessageOutputStream, val, "ar_object_cancel_flag"); ar.objectCancelFlag = val; ar.objectLabelValid=false; ar.boundingBoxValid=false; if (!ar.objectCancelFlag) { if (sei.m_hdr.m_objectLabelPresentFlag) { sei_read_flag(pDecodedMessageOutputStream, val, "ar_object_label_update_flag"); ar.objectLabelValid = val; if (ar.objectLabelValid) { sei_read_uvlc(pDecodedMessageOutputStream, val, "ar_object_label_idx"); ar.objLabelIdx = val; assert(val<256); } } sei_read_flag(pDecodedMessageOutputStream, val, "ar_bounding_box_update_flag"); ar.boundingBoxValid = val; if (ar.boundingBoxValid) { sei_read_flag(pDecodedMessageOutputStream, val, "ar_bounding_box_cancel_flag"); ar.boundingBoxCancelFlag = val; if (!ar.boundingBoxCancelFlag) { sei_read_code(pDecodedMessageOutputStream, 16, val, "ar_bounding_box_top"); ar.boundingBoxTop = val; sei_read_code(pDecodedMessageOutputStream, 16, val, "ar_bounding_box_left"); ar.boundingBoxLeft = val; sei_read_code(pDecodedMessageOutputStream, 16, val, "ar_bounding_box_width"); ar.boundingBoxWidth = val; sei_read_code(pDecodedMessageOutputStream, 16, val, "ar_bounding_box_height"); ar.boundingBoxHeight = val; if (sei.m_hdr.m_partialObjectFlagPresentFlag) { sei_read_flag(pDecodedMessageOutputStream, val, "ar_partial_object_flag"); ar.partialObjectFlag = val; } if (sei.m_hdr.m_objectConfidenceInfoPresentFlag) { sei_read_code(pDecodedMessageOutputStream, sei.m_hdr.m_objectConfidenceLength, val, "ar_object_confidence"); ar.objectConfidence = val; } } } } } } } Void SEIReader::xParseSEICubemapProjection(SEICubemapProjection& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt val; sei_read_flag(pDecodedMessageOutputStream, val, "cmp_cancel_flag"); sei.m_cmpCancelFlag = val; if (!sei.m_cmpCancelFlag) { sei_read_flag(pDecodedMessageOutputStream, val, "cmp_persistence_flag"); sei.m_cmpPersistenceFlag = val; } } Void SEIReader::xParseSEIRegionWisePacking(SEIRegionWisePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt val; sei_read_flag( pDecodedMessageOutputStream, val, "rwp_cancel_flag" ); sei.m_rwpCancelFlag = val; if (!sei.m_rwpCancelFlag) { sei_read_flag( pDecodedMessageOutputStream, val, "rwp_persistence_flag" ); sei.m_rwpPersistenceFlag = val; sei_read_flag( pDecodedMessageOutputStream, val, "constituent_picture_matching_flag" ); sei.m_constituentPictureMatchingFlag = val; sei_read_code( pDecodedMessageOutputStream, 5, val, "rwp_reserved_zero_5bits" ); sei_read_code( pDecodedMessageOutputStream, 8, val, "num_packed_regions" ); sei.m_numPackedRegions = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "proj_picture_width" ); sei.m_projPictureWidth = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "proj_picture_height" ); sei.m_projPictureHeight = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_picture_width" ); sei.m_packedPictureWidth = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_picture_height" ); sei.m_packedPictureHeight = val; sei.m_rwpTransformType.resize(sei.m_numPackedRegions); sei.m_rwpGuardBandFlag.resize(sei.m_numPackedRegions); sei.m_projRegionWidth.resize(sei.m_numPackedRegions); sei.m_projRegionHeight.resize(sei.m_numPackedRegions); sei.m_rwpProjRegionTop.resize(sei.m_numPackedRegions); sei.m_projRegionLeft.resize(sei.m_numPackedRegions); sei.m_packedRegionWidth.resize(sei.m_numPackedRegions); sei.m_packedRegionHeight.resize(sei.m_numPackedRegions); sei.m_packedRegionTop.resize(sei.m_numPackedRegions); sei.m_packedRegionLeft.resize(sei.m_numPackedRegions); sei.m_rwpLeftGuardBandWidth.resize(sei.m_numPackedRegions); sei.m_rwpRightGuardBandWidth.resize(sei.m_numPackedRegions); sei.m_rwpTopGuardBandHeight.resize(sei.m_numPackedRegions); sei.m_rwpBottomGuardBandHeight.resize(sei.m_numPackedRegions); sei.m_rwpGuardBandNotUsedForPredFlag.resize(sei.m_numPackedRegions); sei.m_rwpGuardBandType.resize(4*sei.m_numPackedRegions); for( Int i=0; i < sei.m_numPackedRegions; i++ ) { sei_read_code( pDecodedMessageOutputStream, 4, val, "rwp_reserved_zero_4bits" ); sei_read_code( pDecodedMessageOutputStream, 3, val, "rwp_tTransform_type" ); sei.m_rwpTransformType[i] = val; sei_read_flag( pDecodedMessageOutputStream, val, "rwp_guard_band_flag" ); sei.m_rwpGuardBandFlag[i] = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "proj_region_width" ); sei.m_projRegionWidth[i] = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "proj_region_height" ); sei.m_projRegionHeight[i] = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "rwp_proj_regionTop" ); sei.m_rwpProjRegionTop[i] = val; sei_read_code( pDecodedMessageOutputStream, 32, val, "proj_region_left" ); sei.m_projRegionLeft[i] = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_region_width" ); sei.m_packedRegionWidth[i] = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_region_height" ); sei.m_packedRegionHeight[i] = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_region_top" ); sei.m_packedRegionTop[i] = val; sei_read_code( pDecodedMessageOutputStream, 16, val, "packed_region_left" ); sei.m_packedRegionLeft[i] = val; if( sei.m_rwpGuardBandFlag[i] ) { sei_read_code( pDecodedMessageOutputStream, 8, val, "rwp_left_guard_band_width" ); sei.m_rwpLeftGuardBandWidth[i] = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "rwp_right_guard_band_width" ); sei.m_rwpRightGuardBandWidth[i] = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "rwp_top_guard_band_height" ); sei.m_rwpTopGuardBandHeight[i] = val; sei_read_code( pDecodedMessageOutputStream, 8, val, "rwp_bottom_guard_band_height" ); sei. m_rwpBottomGuardBandHeight[i] = val; sei_read_flag( pDecodedMessageOutputStream, val, "rwp_guard_band_not_used_forPred_flag" ); sei.m_rwpGuardBandNotUsedForPredFlag[i] = val; for( Int j=0; j < 4; j++ ) { sei_read_code( pDecodedMessageOutputStream, 3, val, "rwp_guard_band_type" ); sei.m_rwpGuardBandType[i*4 + j] = val; } sei_read_code( pDecodedMessageOutputStream, 3, val, "rwp_guard_band_reserved_zero_3bits" ); } } } } Void SEIReader::xParseSEIFisheyeVideoInfo(SEIFisheyeVideoInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt val; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei.values = TComSEIFisheyeVideoInfo(); TComSEIFisheyeVideoInfo &info=sei.values; sei_read_flag(pDecodedMessageOutputStream, val, "fisheye_cancel_flag"); info.m_fisheyeCancelFlag = val; if (!info.m_fisheyeCancelFlag) { Int sval; sei_read_flag(pDecodedMessageOutputStream, val, "fisheye_persistence_flag"); info.m_fisheyePersistenceFlag = val; sei_read_code(pDecodedMessageOutputStream, 3, val, "fisheye_view_dimension_idc"); info.m_fisheyeViewDimensionIdc = val; sei_read_code(pDecodedMessageOutputStream, 3, val, "fisheye_reserved_zero_3bits"); sei_read_code(pDecodedMessageOutputStream, 8, val, "fisheye_num_active_area_minus1"); info.m_fisheyeActiveAreas.resize(val+1); for (std::size_t i = 0; i < info.m_fisheyeActiveAreas.size(); i++) { TComSEIFisheyeVideoInfo::ActiveAreaInfo &area=info.m_fisheyeActiveAreas[i]; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_circular_region_centre_x[i]"); area.m_fisheyeCircularRegionCentreX = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_circular_region_centre_y[i]"); area.m_fisheyeCircularRegionCentreY = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_rect_region_top[i]"); area.m_fisheyeRectRegionTop = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_rect_region_left[i]"); area.m_fisheyeRectRegionLeft = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_rect_region_width[i]"); area.m_fisheyeRectRegionWidth = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_rect_region_Height[i]"); area.m_fisheyeRectRegionHeight = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_circular_region_radius[i]"); area.m_fisheyeCircularRegionRadius = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_scene_radius[i]"); area.m_fisheyeSceneRadius = val; sei_read_scode(pDecodedMessageOutputStream, 32, sval, "fisheye_camera_centre_azimuth[i]"); area.m_fisheyeCameraCentreAzimuth = sval; sei_read_scode(pDecodedMessageOutputStream, 32, sval, "fisheye_camera_centre_elevation[i]"); area.m_fisheyeCameraCentreElevation = sval; sei_read_scode(pDecodedMessageOutputStream, 32, sval, "fisheye_camera_centre_tilt[i]"); area.m_fisheyeCameraCentreTilt = sval; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_camera_centre_offset_x[i]"); area.m_fisheyeCameraCentreOffsetX = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_camera_centre_offset_y[i]"); area.m_fisheyeCameraCentreOffsetY = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_camera_centre_offset_z[i]"); area.m_fisheyeCameraCentreOffsetZ = val; sei_read_code(pDecodedMessageOutputStream, 32, val, "fisheye_field_of_view[i]"); area.m_fisheyeFieldOfView = val; sei_read_code(pDecodedMessageOutputStream, 16, val, "fisheye_num_polynomial_coeffs[i]"); area.m_fisheyePolynomialCoeff.resize(val); for (std::size_t j = 0; j < area.m_fisheyePolynomialCoeff.size(); j++) { sei_read_scode(pDecodedMessageOutputStream, 32, sval, "fisheye_polynomial_coeff[i][j]"); area.m_fisheyePolynomialCoeff[j] = sval; } } } } Void SEIReader::xParseSEIColourRemappingInfo(SEIColourRemappingInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream) { UInt uiVal; Int iVal; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc( pDecodedMessageOutputStream, uiVal, "colour_remap_id" ); sei.m_colourRemapId = uiVal; sei_read_flag( pDecodedMessageOutputStream, uiVal, "colour_remap_cancel_flag" ); sei.m_colourRemapCancelFlag = uiVal; if( !sei.m_colourRemapCancelFlag ) { sei_read_flag( pDecodedMessageOutputStream, uiVal, "colour_remap_persistence_flag" ); sei.m_colourRemapPersistenceFlag = uiVal; sei_read_flag( pDecodedMessageOutputStream, uiVal, "colour_remap_video_signal_info_present_flag" ); sei.m_colourRemapVideoSignalInfoPresentFlag = uiVal; if ( sei.m_colourRemapVideoSignalInfoPresentFlag ) { sei_read_flag( pDecodedMessageOutputStream, uiVal, "colour_remap_full_range_flag" ); sei.m_colourRemapFullRangeFlag = uiVal; sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "colour_remap_primaries" ); sei.m_colourRemapPrimaries = uiVal; sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "colour_remap_transfer_function" ); sei.m_colourRemapTransferFunction = uiVal; sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "colour_remap_matrix_coefficients" ); sei.m_colourRemapMatrixCoefficients = uiVal; } sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "colour_remap_input_bit_depth" ); sei.m_colourRemapInputBitDepth = uiVal; sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "colour_remap_bit_depth" ); sei.m_colourRemapBitDepth = uiVal; for( Int c=0 ; c<3 ; c++ ) { sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "pre_lut_num_val_minus1[c]" ); sei.m_preLutNumValMinus1[c] = (uiVal==0) ? 1 : uiVal; sei.m_preLut[c].resize(sei.m_preLutNumValMinus1[c]+1); if( uiVal> 0 ) { for ( Int i=0 ; i<=sei.m_preLutNumValMinus1[c] ; i++ ) { sei_read_code( pDecodedMessageOutputStream, (( sei.m_colourRemapInputBitDepth + 7 ) >> 3 ) << 3, uiVal, "pre_lut_coded_value[c][i]" ); sei.m_preLut[c][i].codedValue = uiVal; sei_read_code( pDecodedMessageOutputStream, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, uiVal, "pre_lut_target_value[c][i]" ); sei.m_preLut[c][i].targetValue = uiVal; } } else // pre_lut_num_val_minus1[c] == 0 { sei.m_preLut[c][0].codedValue = 0; sei.m_preLut[c][0].targetValue = 0; sei.m_preLut[c][1].codedValue = (1 << sei.m_colourRemapInputBitDepth) - 1 ; sei.m_preLut[c][1].targetValue = (1 << sei.m_colourRemapBitDepth) - 1 ; } } sei_read_flag( pDecodedMessageOutputStream, uiVal, "colour_remap_matrix_present_flag" ); sei.m_colourRemapMatrixPresentFlag = uiVal; if( sei.m_colourRemapMatrixPresentFlag ) { sei_read_code( pDecodedMessageOutputStream, 4, uiVal, "log2_matrix_denom" ); sei.m_log2MatrixDenom = uiVal; for ( Int c=0 ; c<3 ; c++ ) { for ( Int i=0 ; i<3 ; i++ ) { sei_read_svlc( pDecodedMessageOutputStream, iVal, "colour_remap_coeffs[c][i]" ); sei.m_colourRemapCoeffs[c][i] = iVal; } } } else // setting default matrix (I3) { sei.m_log2MatrixDenom = 10; for ( Int c=0 ; c<3 ; c++ ) { for ( Int i=0 ; i<3 ; i++ ) { sei.m_colourRemapCoeffs[c][i] = (c==i) << sei.m_log2MatrixDenom; } } } for( Int c=0 ; c<3 ; c++ ) { sei_read_code( pDecodedMessageOutputStream, 8, uiVal, "post_lut_num_val_minus1[c]" ); sei.m_postLutNumValMinus1[c] = (uiVal==0) ? 1 : uiVal; sei.m_postLut[c].resize(sei.m_postLutNumValMinus1[c]+1); if( uiVal > 0 ) { for ( Int i=0 ; i<=sei.m_postLutNumValMinus1[c] ; i++ ) { sei_read_code( pDecodedMessageOutputStream, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, uiVal, "post_lut_coded_value[c][i]" ); sei.m_postLut[c][i].codedValue = uiVal; sei_read_code( pDecodedMessageOutputStream, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, uiVal, "post_lut_target_value[c][i]" ); sei.m_postLut[c][i].targetValue = uiVal; } } else { sei.m_postLut[c][0].codedValue = 0; sei.m_postLut[c][0].targetValue = 0; sei.m_postLut[c][1].targetValue = (1 << sei.m_colourRemapBitDepth) - 1; sei.m_postLut[c][1].codedValue = (1 << sei.m_colourRemapBitDepth) - 1; } } } } Void SEIReader::xParseSEIDeinterlaceFieldIdentification( SEIDeinterlaceFieldIdentification& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream ) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_flag(pDecodedMessageOutputStream, code, "deinterlaced_picture_source_parity_flag"); sei.m_deinterlacedPictureSourceParityFlag = code!=0; } Void SEIReader::xParseSEIContentLightLevelInfo( SEIContentLightLevelInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream ) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code(pDecodedMessageOutputStream, 16, code, "max_content_light_level"); sei.m_maxContentLightLevel = code; sei_read_code(pDecodedMessageOutputStream, 16, code, "max_pic_average_light_level"); sei.m_maxPicAverageLightLevel = code; } Void SEIReader::xParseSEIDependentRAPIndication( SEIDependentRAPIndication& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream ) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); } Void SEIReader::xParseSEICodedRegionCompletion( SEICodedRegionCompletion& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream ) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_uvlc(pDecodedMessageOutputStream, code, "next_segment_address"); sei.m_nextSegmentAddress= code; if (code) { sei_read_flag(pDecodedMessageOutputStream, code, "independent_slice_segment_flag"); sei.m_independentSliceSegmentFlag = code!=0; } else { sei.m_independentSliceSegmentFlag=false; // initialise to known value. } } Void SEIReader::xParseSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics& sei, UInt payloadSize, ostream* pDecodedMessageOutputStream) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code(pDecodedMessageOutputStream, 8, code, "preferred_transfer_characteristics"); sei.m_preferredTransferCharacteristics = code; } Void SEIReader::xParseSEIAmbientViewingEnvironment( SEIAmbientViewingEnvironment& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream ) { UInt code; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); sei_read_code(pDecodedMessageOutputStream, 32, code, "ambient_illuminance"); sei.m_ambientIlluminance= code; sei_read_code(pDecodedMessageOutputStream, 16, code, "ambient_light_x"); sei.m_ambientLightX = (UShort)code; sei_read_code(pDecodedMessageOutputStream, 16, code, "ambient_light_y"); sei.m_ambientLightY = (UShort)code; } Void SEIReader::xParseSEIRegionalNesting( SEIRegionalNesting& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream ) { UInt uiCode; output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt numRegions, numSEIs; sei_read_code(pDecodedMessageOutputStream, 16, uiCode, "regional_nesting_id"); sei_read_code(pDecodedMessageOutputStream, 8, uiCode, "regional_nesting_num_rect_regions"); numRegions = uiCode; sei.clearRegions(); for(UInt i = 0; i < numRegions; i++) { RNSEIWindow region; Int lOffset, rOffset, tOffset, bOffset, regionId; sei_read_code(pDecodedMessageOutputStream, 8, uiCode, "regional_nesting_rect_region_id"); regionId = uiCode; sei_read_code(pDecodedMessageOutputStream, 16, uiCode, "regional_nesting_rect_left_offset"); lOffset = uiCode; sei_read_code(pDecodedMessageOutputStream, 16, uiCode, "regional_nesting_rect_right_offset"); rOffset = uiCode; sei_read_code(pDecodedMessageOutputStream, 16, uiCode, "regional_nesting_rect_top_offset"); tOffset = uiCode; sei_read_code(pDecodedMessageOutputStream, 16, uiCode, "regional_nesting_rect_bottom_offset"); bOffset = uiCode; region.setRegionId(regionId); region.setWindow(lOffset, rOffset, tOffset, bOffset); sei.addRegion(®ion); } sei_read_code(pDecodedMessageOutputStream, 8, uiCode, "num_sei_messages_in_regional_nesting_minus1"); numSEIs = uiCode + 1; for(UInt i = 0; i < numSEIs; i++) { SEIRegionalNesting::SEIListOfIndices seiWithRegionIndices; UInt numRegionsForSEI; sei_read_code(pDecodedMessageOutputStream, 8, uiCode, "num_regions_for_sei_message[i]"); numRegionsForSEI = uiCode; for(UInt j = 0; j < numRegionsForSEI; j++) { sei_read_code(pDecodedMessageOutputStream, 8, uiCode, "regional_nesting_sei_region_idx[i][j]"); seiWithRegionIndices.m_listOfIndices.push_back(uiCode); } SEIMessages seiReg; xReadSEImessage(seiReg, NAL_UNIT_PREFIX_SEI, sps, pDecodedMessageOutputStream, SEI::regional_nesting_sei_messages, std::string("")); seiWithRegionIndices.m_seiMessage = seiReg.front(); sei.addRegionalSEI( seiWithRegionIndices ) ; } } #if JCTVC_AD0021_SEI_MANIFEST Void SEIReader::xParseSEISEIManifest(SEIManifest& sei, UInt payloadSize, std::ostream* pDecodedMessageOutputStream) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt val; sei_read_code(pDecodedMessageOutputStream, 16, val, "manifest_num_sei_msg_types"); sei.m_manifestNumSeiMsgTypes = val; if (sei.m_manifestNumSeiMsgTypes > 0) { sei.m_manifestSeiPayloadType.resize(sei.m_manifestNumSeiMsgTypes); sei.m_manifestSeiDescription.resize(sei.m_manifestNumSeiMsgTypes); for (Int i = 0; i < sei.m_manifestNumSeiMsgTypes; i++) { sei_read_code(pDecodedMessageOutputStream, 16, val, "manifest_sei_payload_types"); sei.m_manifestSeiPayloadType[i] = val; sei_read_code(pDecodedMessageOutputStream, 8, val, "manifest_sei_description"); sei.m_manifestSeiDescription[i] = val; } } } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Void SEIReader::xParseSEISEIPrefixIndication(SEIPrefixIndication& sei, UInt payloadSize, std::ostream* pDecodedMessageOutputStream) { output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); UInt val; UInt bitsRead = 0; sei_read_code(pDecodedMessageOutputStream, 16, val, "prefix_sei_payload_type"); sei.m_prefixSeiPayloadType = val; sei_read_code(pDecodedMessageOutputStream, 8, val, "num_sei_prefix_indications_minus1"); sei.m_numSeiPrefixIndicationsMinus1 = val; if (sei.m_numSeiPrefixIndicationsMinus1 >= 0) { sei.m_numBitsInPrefixIndicationMinus1.resize(sei.m_numSeiPrefixIndicationsMinus1 + 1); sei.m_seiPrefixDataBit.resize(sei.m_numSeiPrefixIndicationsMinus1 + 1); for (Int i = 0; i <= sei.m_numSeiPrefixIndicationsMinus1; i++) { sei_read_code(pDecodedMessageOutputStream, 16, val, "num_bits_in_prefix_indication_minus1"); sei.m_numBitsInPrefixIndicationMinus1[i] = val; sei.m_seiPrefixDataBit[i].resize(sei.m_numBitsInPrefixIndicationMinus1[i] + 1); for (Int j = 0; j <= sei.m_numBitsInPrefixIndicationMinus1[i]; j++) { sei_read_code(pDecodedMessageOutputStream, 1, val, "sei_prefix_data_bit"); sei.m_seiPrefixDataBit[i][j] = val; bitsRead += 1; } while (bitsRead % 8 != 0) { sei_read_code(pDecodedMessageOutputStream, 1, val, "byte_alignment_bit_equal_to_one"); bitsRead += 1; } } } } #endif //! \} HM-HM-18.0/source/Lib/TLibDecoder/SEIread.h000066400000000000000000000273101442026013100200170ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SEIread.h \brief reading functionality for SEI messages */ #ifndef __SEIREAD__ #define __SEIREAD__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 //! \ingroup TLibDecoder //! \{ #include "SyntaxElementParser.h" #include "TLibCommon/SEI.h" class TComInputBitstream; class SEIReader: public SyntaxElementParser { public: SEIReader() {}; virtual ~SEIReader() {}; Void parseSEImessage(TComInputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); protected: Void xReadSEImessage (SEIMessages& seis, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream, const vector& allowedSeiTypes, std::string const &typeName); Void xReadSEIPayloadData (Int const payloadType, Int const payloadSize, SEI *&sei, const NalUnitType nalUnitType, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream, std::string const &typeName); Void xParseSEIBufferingPeriod (SEIBufferingPeriod& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); Void xParseSEIPictureTiming (SEIPictureTiming& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); Void xParseSEIPanScanRect (SEIPanScanRect& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIFillerPayload (SEIFillerPayload& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIUserDataRegistered (SEIUserDataRegistered& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIUserDataUnregistered (SEIUserDataUnregistered &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIRecoveryPoint (SEIRecoveryPoint& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEISceneInfo (SEISceneInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIPictureSnapshot (SEIPictureSnapshot& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIProgressiveRefinementSegmentStart(SEIProgressiveRefinementSegmentStart& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIProgressiveRefinementSegmentEnd(SEIProgressiveRefinementSegmentEnd& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIFilmGrainCharacteristics (SEIFilmGrainCharacteristics& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIPostFilterHint (SEIPostFilterHint& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); Void xParseSEIToneMappingInfo (SEIToneMappingInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIFramePacking (SEIFramePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIDisplayOrientation (SEIDisplayOrientation &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIGreenMetadataInfo (SEIGreenMetadataInfo& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEISOPDescription (SEISOPDescription &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIActiveParameterSets (SEIActiveParameterSets &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIDecodingUnitInfo (SEIDecodingUnitInfo& sei, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); Void xParseSEITemporalLevel0Index (SEITemporalLevel0Index &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIDecodedPictureHash (SEIDecodedPictureHash& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIScalableNesting (SEIScalableNesting& sei, const NalUnitType nalUnitType, UInt payloadSize, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream); Void xParseSEIRegionRefreshInfo (SEIRegionRefreshInfo &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEINoDisplay (SEINoDisplay &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEITimeCode (SEITimeCode& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIMasteringDisplayColourVolume (SEIMasteringDisplayColourVolume& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEISegmentedRectFramePacking (SEISegmentedRectFramePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEITempMotionConstraintsTileSets (SEITempMotionConstrainedTileSets& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); #if MCTS_EXTRACTION Void xParseSEIMCTSExtractionInfoSet (SEIMCTSExtractionInfoSet& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); #endif Void xParseSEIChromaResamplingFilterHint (SEIChromaResamplingFilterHint& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIKneeFunctionInfo (SEIKneeFunctionInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIContentColourVolume (SEIContentColourVolume& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIEquirectangularProjection (SEIEquirectangularProjection &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEISphereRotation (SEISphereRotation &sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIOmniViewport (SEIOmniViewport& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEICubemapProjection (SEICubemapProjection& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIAnnotatedRegions (SEIAnnotatedRegions& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIRegionWisePacking (SEIRegionWisePacking& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIFisheyeVideoInfo(SEIFisheyeVideoInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIColourRemappingInfo (SEIColourRemappingInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIDeinterlaceFieldIdentification(SEIDeinterlaceFieldIdentification& sei,UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIContentLightLevelInfo (SEIContentLightLevelInfo& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIDependentRAPIndication (SEIDependentRAPIndication& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEICodedRegionCompletion (SEICodedRegionCompletion& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIAmbientViewingEnvironment (SEIAmbientViewingEnvironment& sei, UInt payLoadSize, std::ostream *pDecodedMessageOutputStream); Void xParseSEIRegionalNesting ( SEIRegionalNesting& sei, UInt payloadSize, const TComSPS* sps, std::ostream *pDecodedMessageOutputStream ); #if SHUTTER_INTERVAL_SEI_MESSAGE Void xParseSEIShutterInterval (SEIShutterIntervalInfo& sei, UInt payloadSize, std::ostream *pDecodedMessageOutputStream); #endif #if JCTVC_AD0021_SEI_MANIFEST Void xParseSEISEIManifest(SEIManifest & sei, UInt payloadSize, std::ostream * pDecodedMessageOutputStream); #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Void xParseSEISEIPrefixIndication(SEIPrefixIndication & sei, UInt payloadSize, std::ostream * pDecodedMessageOutputStream); #endif Void sei_read_scode(std::ostream *pOS, UInt uiLength, Int& ruiCode, const TChar *pSymbolName); Void sei_read_code(std::ostream *pOS, UInt uiLength, UInt& ruiCode, const TChar *pSymbolName); Void sei_read_uvlc(std::ostream *pOS, UInt& ruiCode, const TChar *pSymbolName); Void sei_read_svlc(std::ostream *pOS, Int& ruiCode, const TChar *pSymbolName); Void sei_read_flag(std::ostream *pOS, UInt& ruiCode, const TChar *pSymbolName); }; //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/SyntaxElementParser.cpp000066400000000000000000000213351442026013100230540ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SyntaxElementParser.cpp \brief Parsing functionality high level syntax */ //! \ingroup TLibDecoder //! \{ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComRom.h" #include "TLibCommon/TComBitStream.h" #include "SyntaxElementParser.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif #if ENC_DEC_TRACE Void xTraceAccessUnitDelimiter () { fprintf( g_hTrace, "=========== Access Unit Delimiter ===========\n"); } Void xTraceFillerData () { fprintf( g_hTrace, "=========== Filler Data ===========\n"); } #endif #if DECODER_PARTIAL_CONFORMANCE_CHECK!=0 Void SyntaxElementParser::xReadSCodeChk ( UInt length, Int& val, const TChar *pSymbolName, const Int minValIncl, const Int maxValIncl ) { READ_SCODE(length, val, pSymbolName); TDecConformanceCheck::checkRange(val, pSymbolName, minValIncl, maxValIncl); } Void SyntaxElementParser::xReadCodeChk ( UInt length, UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ) { READ_CODE(length, val, pSymbolName); TDecConformanceCheck::checkRange(val, pSymbolName, minValIncl, maxValIncl); } Void SyntaxElementParser::xReadUvlcChk ( UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ) { READ_UVLC(val, pSymbolName); TDecConformanceCheck::checkRange(val, pSymbolName, minValIncl, maxValIncl); } Void SyntaxElementParser::xReadSvlcChk ( Int& val, const TChar *pSymbolName, const Int minValIncl, const Int maxValIncl ) { READ_SVLC(val, pSymbolName); TDecConformanceCheck::checkRange(val, pSymbolName, minValIncl, maxValIncl); } Void SyntaxElementParser::xReadFlagChk ( UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ) { READ_FLAG(val, pSymbolName); TDecConformanceCheck::checkRange(val, pSymbolName, minValIncl, maxValIncl); } #endif // ==================================================================================================================== // Protected member functions // ==================================================================================================================== #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void SyntaxElementParser::xReadSCode (UInt uiLength, Int& rValue, const TChar *pSymbolName) #else Void SyntaxElementParser::xReadSCode (UInt uiLength, Int& rValue) #endif { UInt val; assert ( uiLength > 0 && uiLength<=32); m_pcBitstream->read (uiLength, val); rValue= uiLength>=32 ? Int(val) : ( (-Int( val & (UInt(1)<<(uiLength-1)))) | Int(val) ); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(pSymbolName, uiLength, rValue); #endif #if ENC_DEC_TRACE fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); if (uiLength < 10) { fprintf( g_hTrace, "%-50s i(%d) : %d\n", pSymbolName, uiLength, rValue ); } else { fprintf( g_hTrace, "%-50s i(%d) : %d\n", pSymbolName, uiLength, rValue ); } fflush ( g_hTrace ); #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void SyntaxElementParser::xReadCode (UInt uiLength, UInt& rValue, const TChar *pSymbolName) #else Void SyntaxElementParser::xReadCode (UInt uiLength, UInt& rValue) #endif { assert ( uiLength > 0 ); m_pcBitstream->read (uiLength, rValue); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(pSymbolName, uiLength, rValue); #endif #if ENC_DEC_TRACE fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); if (uiLength < 10) { fprintf( g_hTrace, "%-50s u(%d) : %u\n", pSymbolName, uiLength, rValue ); } else { fprintf( g_hTrace, "%-50s u(%d) : %u\n", pSymbolName, uiLength, rValue ); } fflush ( g_hTrace ); #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void SyntaxElementParser::xReadUvlc( UInt& rValue, const TChar *pSymbolName) #else Void SyntaxElementParser::xReadUvlc( UInt& rValue) #endif { UInt uiVal = 0; UInt uiCode = 0; UInt uiLength; m_pcBitstream->read( 1, uiCode ); #if RExt__DECODER_DEBUG_BIT_STATISTICS UInt totalLen=1; #endif if( 0 == uiCode ) { uiLength = 0; while( ! ( uiCode & 1 )) { m_pcBitstream->read( 1, uiCode ); uiLength++; } m_pcBitstream->read( uiLength, uiVal ); uiVal += (1 << uiLength)-1; #if RExt__DECODER_DEBUG_BIT_STATISTICS totalLen+=uiLength+uiLength; #endif } rValue = uiVal; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(pSymbolName, Int(totalLen), rValue); #endif #if ENC_DEC_TRACE fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s ue(v) : %u\n", pSymbolName, rValue ); fflush ( g_hTrace ); #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void SyntaxElementParser::xReadSvlc( Int& rValue, const TChar *pSymbolName) #else Void SyntaxElementParser::xReadSvlc( Int& rValue) #endif { UInt uiBits = 0; m_pcBitstream->read( 1, uiBits ); #if RExt__DECODER_DEBUG_BIT_STATISTICS UInt totalLen=1; #endif if( 0 == uiBits ) { UInt uiLength = 0; while( ! ( uiBits & 1 )) { m_pcBitstream->read( 1, uiBits ); uiLength++; } m_pcBitstream->read( uiLength, uiBits ); uiBits += (1 << uiLength); rValue = ( uiBits & 1) ? -(Int)(uiBits>>1) : (Int)(uiBits>>1); #if RExt__DECODER_DEBUG_BIT_STATISTICS totalLen+=uiLength+uiLength; #endif } else { rValue = 0; } #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(pSymbolName, Int(totalLen), rValue); #endif #if ENC_DEC_TRACE fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s se(v) : %d\n", pSymbolName, rValue ); fflush ( g_hTrace ); #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void SyntaxElementParser::xReadFlag (UInt& rValue, const TChar *pSymbolName) #else Void SyntaxElementParser::xReadFlag (UInt& rValue) #endif { m_pcBitstream->read( 1, rValue ); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(pSymbolName, 1, Int(rValue)); #endif #if ENC_DEC_TRACE fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(1) : %d\n", pSymbolName, rValue ); fflush ( g_hTrace ); #endif } Void SyntaxElementParser::xReadRbspTrailingBits() { UInt bit; READ_FLAG( bit, "rbsp_stop_one_bit"); assert (bit==1); Int cnt = 0; while (m_pcBitstream->getNumBitsUntilByteAligned()) { READ_FLAG( bit, "rbsp_alignment_zero_bit"); assert (bit==0); cnt++; } assert(cnt<8); } Void AUDReader::parseAccessUnitDelimiter(TComInputBitstream* bs, UInt &picType) { setBitstream(bs); #if ENC_DEC_TRACE xTraceAccessUnitDelimiter(); #endif READ_CODE (3, picType, "pic_type"); xReadRbspTrailingBits(); } Void FDReader::parseFillerData(TComInputBitstream* bs, UInt &fdSize) { setBitstream(bs); #if ENC_DEC_TRACE xTraceFillerData(); #endif UInt ffByte; fdSize = 0; while( m_pcBitstream->getNumBitsLeft() >8 ) { READ_CODE (8, ffByte, "ff_byte"); assert (ffByte==0xff); fdSize++; } xReadRbspTrailingBits(); } //! \} HM-HM-18.0/source/Lib/TLibDecoder/SyntaxElementParser.h000066400000000000000000000154421442026013100225230ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SyntaxElementParser.h \brief Parsing functionality high level syntax */ #ifndef __SYNTAXELEMENTPARSER__ #define __SYNTAXELEMENTPARSER__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/TComRom.h" #include "TDecConformance.h" #if DECODER_PARTIAL_CONFORMANCE_CHECK!=0 #define READ_SCODE_CHK(length, code, name, minValIncl, maxValIncl) xReadSCodeChk ( length, code, name, minValIncl, maxValIncl ) #define READ_CODE_CHK(length, code, name, minValIncl, maxValIncl) xReadCodeChk ( length, code, name, minValIncl, maxValIncl ) #define READ_UVLC_CHK( code, name, minValIncl, maxValIncl) xReadUvlcChk ( code, name, minValIncl, maxValIncl ) #define READ_SVLC_CHK( code, name, minValIncl, maxValIncl) xReadSvlcChk ( code, name, minValIncl, maxValIncl ) #define READ_FLAG_CHK( code, name, minValIncl, maxValIncl) xReadFlagChk ( code, name, minValIncl, maxValIncl ) #elif RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE #define READ_SCODE_CHK(length, code, name, minValIncl, maxValIncl) xReadSCode ( length, code, name ) #define READ_CODE_CHK(length, code, name, minValIncl, maxValIncl) xReadCode ( length, code, name ) #define READ_UVLC_CHK( code, name, minValIncl, maxValIncl) xReadUvlc ( code, name ) #define READ_SVLC_CHK( code, name, minValIncl, maxValIncl) xReadSvlc ( code, name ) #define READ_FLAG_CHK( code, name, minValIncl, maxValIncl) xReadFlag ( code, name ) #else #define READ_SCODE_CHK(length, code, name, minValIncl, maxValIncl) xReadSCode ( length, code ) #define READ_CODE_CHK(length, code, name, minValIncl, maxValIncl) xReadCode ( length, code ) #define READ_UVLC_CHK( code, name, minValIncl, maxValIncl) xReadUvlc ( code ) #define READ_SVLC_CHK( code, name, minValIncl, maxValIncl) xReadSvlc ( code ) #define READ_FLAG_CHK( code, name, minValIncl, maxValIncl) xReadFlag ( code ) #endif #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE #define READ_SCODE(length, code, name) xReadSCode ( length, code, name ) #define READ_CODE(length, code, name) xReadCode ( length, code, name ) #define READ_UVLC( code, name) xReadUvlc ( code, name ) #define READ_SVLC( code, name) xReadSvlc ( code, name ) #define READ_FLAG( code, name) xReadFlag ( code, name ) #else #define READ_SCODE(length, code, name) xReadSCode ( length, code ) #define READ_CODE(length, code, name) xReadCode ( length, code ) #define READ_UVLC( code, name) xReadUvlc ( code ) #define READ_SVLC( code, name) xReadSvlc ( code ) #define READ_FLAG( code, name) xReadFlag ( code ) #endif //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class SyntaxElementParser { protected: TComInputBitstream* m_pcBitstream; SyntaxElementParser() : m_pcBitstream (NULL) {}; virtual ~SyntaxElementParser() {}; #if DECODER_PARTIAL_CONFORMANCE_CHECK!=0 Void xReadSCodeChk ( UInt length, Int& val, const TChar *pSymbolName, const Int minValIncl, const Int maxValIncl ); Void xReadCodeChk ( UInt length, UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ); Void xReadUvlcChk ( UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ); Void xReadSvlcChk ( Int& val, const TChar *pSymbolName, const Int minValIncl, const Int maxValIncl ); Void xReadFlagChk ( UInt& val, const TChar *pSymbolName, const UInt minValIncl, const UInt maxValIncl ); #endif #if RExt__DECODER_DEBUG_BIT_STATISTICS || ENC_DEC_TRACE Void xReadSCode ( UInt length, Int& val, const TChar *pSymbolName ); Void xReadCode ( UInt length, UInt& val, const TChar *pSymbolName ); Void xReadUvlc ( UInt& val, const TChar *pSymbolName ); Void xReadSvlc ( Int& val, const TChar *pSymbolName ); Void xReadFlag ( UInt& val, const TChar *pSymbolName ); #else Void xReadSCode ( UInt length, Int& val ); Void xReadCode ( UInt length, UInt& val ); Void xReadUvlc ( UInt& val ); Void xReadSvlc ( Int& val ); Void xReadFlag ( UInt& val ); #endif public: Void setBitstream ( TComInputBitstream* p ) { m_pcBitstream = p; } TComInputBitstream* getBitstream() { return m_pcBitstream; } protected: Void xReadRbspTrailingBits(); }; class AUDReader: public SyntaxElementParser { public: AUDReader() {}; virtual ~AUDReader() {}; Void parseAccessUnitDelimiter(TComInputBitstream* bs, UInt &picType); }; class FDReader: public SyntaxElementParser { public: FDReader() {}; virtual ~FDReader() {}; Void parseFillerData(TComInputBitstream* bs, UInt &fdSize); }; //! \} #endif // !defined(__SYNTAXELEMENTPARSER__) HM-HM-18.0/source/Lib/TLibDecoder/TDecBinCoder.h000066400000000000000000000073021442026013100207670ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecBinCoder.h \brief binary entropy decoder interface */ #ifndef __TDECBINCODER__ #define __TDECBINCODER__ #include "TLibCommon/ContextModel.h" #include "TLibCommon/TComBitStream.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS class TComCodingStatisticsClassType; #endif //! \ingroup TLibDecoder //! \{ class TDecBinCABAC; class TDecBinIf { public: virtual Void init ( TComInputBitstream* pcTComBitstream ) = 0; virtual Void uninit () = 0; virtual Void start () = 0; virtual Void finish () = 0; #if RExt__DECODER_DEBUG_BIT_STATISTICS virtual Void decodeBin ( UInt& ruiBin, ContextModel& rcCtxModel, const class TComCodingStatisticsClassType &whichStat ) = 0; virtual Void decodeBinEP ( UInt& ruiBin , const class TComCodingStatisticsClassType &whichStat ) = 0; virtual Void decodeBinsEP ( UInt& ruiBins, Int numBins , const class TComCodingStatisticsClassType &whichStat ) = 0; #else virtual Void decodeBin ( UInt& ruiBin, ContextModel& rcCtxModel ) = 0; virtual Void decodeBinEP ( UInt& ruiBin ) = 0; virtual Void decodeBinsEP ( UInt& ruiBins, Int numBins ) = 0; #endif virtual Void align () = 0; virtual Void decodeBinTrm ( UInt& ruiBin ) = 0; virtual Void xReadPCMCode ( UInt uiLength, UInt& ruiCode) = 0; virtual ~TDecBinIf() {} virtual Void copyState ( const TDecBinIf* pcTDecBinIf ) = 0; virtual TDecBinCABAC* getTDecBinCABAC () { return 0; } virtual const TDecBinCABAC* getTDecBinCABAC () const { return 0; } }; //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecBinCoderCABAC.cpp000066400000000000000000000246561442026013100220470ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecBinCoderCABAC.cpp \brief binary entropy decoder of CABAC */ #include "TDecBinCoderCABAC.h" #include "TLibCommon/Debug.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif //! \ingroup TLibDecoder //! \{ TDecBinCABAC::TDecBinCABAC() : m_pcTComBitstream( 0 ) { } TDecBinCABAC::~TDecBinCABAC() { } Void TDecBinCABAC::init( TComInputBitstream* pcTComBitstream ) { m_pcTComBitstream = pcTComBitstream; } Void TDecBinCABAC::uninit() { m_pcTComBitstream = 0; } Void TDecBinCABAC::start() { assert( m_pcTComBitstream->getNumBitsUntilByteAligned() == 0 ); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(STATS__CABAC_INITIALISATION, 512, 510, 0); #endif m_uiRange = 510; m_bitsNeeded = -8; m_uiValue = (m_pcTComBitstream->readByte() << 8); m_uiValue |= m_pcTComBitstream->readByte(); } Void TDecBinCABAC::finish() { UInt lastByte; m_pcTComBitstream->peekPreviousByte( lastByte ); // Check for proper stop/alignment pattern assert( ((lastByte << (8 + m_bitsNeeded)) & 0xff) == 0x80 ); } /** - Copy CABAC state. . \param pcTDecBinIf The source CABAC engine. */ Void TDecBinCABAC::copyState( const TDecBinIf* pcTDecBinIf ) { const TDecBinCABAC* pcTDecBinCABAC = pcTDecBinIf->getTDecBinCABAC(); m_uiRange = pcTDecBinCABAC->m_uiRange; m_uiValue = pcTDecBinCABAC->m_uiValue; m_bitsNeeded= pcTDecBinCABAC->m_bitsNeeded; } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecBinCABAC::decodeBin( UInt& ruiBin, ContextModel &rcCtxModel, const TComCodingStatisticsClassType &whichStat ) #else Void TDecBinCABAC::decodeBin( UInt& ruiBin, ContextModel &rcCtxModel ) #endif { #if DEBUG_CABAC_BINS const UInt startingRange = m_uiRange; #endif UInt uiLPS = TComCABACTables::sm_aucLPSTable[ rcCtxModel.getState() ][ ( m_uiRange >> 6 ) - 4 ]; m_uiRange -= uiLPS; UInt scaledRange = m_uiRange << 7; if( m_uiValue < scaledRange ) { // MPS path ruiBin = rcCtxModel.getMps(); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(whichStat, m_uiRange+uiLPS, m_uiRange, Int(ruiBin)); #endif rcCtxModel.updateMPS(); if ( scaledRange < ( 256 << 7 ) ) { m_uiRange = scaledRange >> 6; m_uiValue += m_uiValue; if ( ++m_bitsNeeded == 0 ) { m_bitsNeeded = -8; m_uiValue += m_pcTComBitstream->readByte(); } } } else { // LPS path ruiBin = 1 - rcCtxModel.getMps(); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(whichStat, m_uiRange+uiLPS, uiLPS, Int(ruiBin)); #endif Int numBits = TComCABACTables::sm_aucRenormTable[ uiLPS >> 3 ]; m_uiValue = ( m_uiValue - scaledRange ) << numBits; m_uiRange = uiLPS << numBits; rcCtxModel.updateLPS(); m_bitsNeeded += numBits; if ( m_bitsNeeded >= 0 ) { m_uiValue += m_pcTComBitstream->readByte() << m_bitsNeeded; m_bitsNeeded -= 8; } } #if DEBUG_CABAC_BINS if ((g_debugCounter + debugCabacBinWindow) >= debugCabacBinTargetLine) { std::cout << g_debugCounter << ": coding bin value " << ruiBin << ", range = [" << startingRange << "->" << m_uiRange << "]\n"; } if (g_debugCounter >= debugCabacBinTargetLine) { UChar breakPointThis; breakPointThis = 7; } if (g_debugCounter >= (debugCabacBinTargetLine + debugCabacBinWindow)) { exit(0); } g_debugCounter++; #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecBinCABAC::decodeBinEP( UInt& ruiBin, const TComCodingStatisticsClassType &whichStat ) #else Void TDecBinCABAC::decodeBinEP( UInt& ruiBin ) #endif { if (m_uiRange == 256) { #if RExt__DECODER_DEBUG_BIT_STATISTICS decodeAlignedBinsEP(ruiBin, 1, whichStat); #else decodeAlignedBinsEP(ruiBin, 1); #endif return; } m_uiValue += m_uiValue; if ( ++m_bitsNeeded >= 0 ) { m_bitsNeeded = -8; m_uiValue += m_pcTComBitstream->readByte(); } ruiBin = 0; UInt scaledRange = m_uiRange << 7; if ( m_uiValue >= scaledRange ) { ruiBin = 1; m_uiValue -= scaledRange; } #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(whichStat, 1, Int(ruiBin)); #endif } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecBinCABAC::decodeBinsEP( UInt& ruiBin, Int numBins, const TComCodingStatisticsClassType &whichStat ) #else Void TDecBinCABAC::decodeBinsEP( UInt& ruiBin, Int numBins ) #endif { if (m_uiRange == 256) { #if RExt__DECODER_DEBUG_BIT_STATISTICS decodeAlignedBinsEP(ruiBin, numBins, whichStat); #else decodeAlignedBinsEP(ruiBin, numBins); #endif return; } UInt bins = 0; #if RExt__DECODER_DEBUG_BIT_STATISTICS Int origNumBins=numBins; #endif while ( numBins > 8 ) { m_uiValue = ( m_uiValue << 8 ) + ( m_pcTComBitstream->readByte() << ( 8 + m_bitsNeeded ) ); UInt scaledRange = m_uiRange << 15; for ( Int i = 0; i < 8; i++ ) { bins += bins; scaledRange >>= 1; if ( m_uiValue >= scaledRange ) { bins++; m_uiValue -= scaledRange; } } numBins -= 8; } m_bitsNeeded += numBins; m_uiValue <<= numBins; if ( m_bitsNeeded >= 0 ) { m_uiValue += m_pcTComBitstream->readByte() << m_bitsNeeded; m_bitsNeeded -= 8; } UInt scaledRange = m_uiRange << ( numBins + 7 ); for ( Int i = 0; i < numBins; i++ ) { bins += bins; scaledRange >>= 1; if ( m_uiValue >= scaledRange ) { bins++; m_uiValue -= scaledRange; } } ruiBin = bins; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(whichStat, origNumBins, Int(ruiBin)); #endif } Void TDecBinCABAC::align() { #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(STATS__CABAC_EP_BIT_ALIGNMENT, m_uiRange, 256, 0); #endif m_uiRange = 256; } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecBinCABAC::decodeAlignedBinsEP( UInt& ruiBins, Int numBins, const class TComCodingStatisticsClassType &whichStat ) #else Void TDecBinCABAC::decodeAlignedBinsEP( UInt& ruiBins, Int numBins ) #endif { Int binsRemaining = numBins; ruiBins = 0; assert(m_uiRange == 256); //aligned decode only works when range = 256 while (binsRemaining > 0) { const UInt binsToRead = std::min(binsRemaining, 8); //read bytes if able to take advantage of the system's byte-read function const UInt binMask = (1 << binsToRead) - 1; //The MSB of m_uiValue is known to be 0 because range is 256. Therefore: // > The comparison against the symbol range of 128 is simply a test on the next-most-significant bit // > "Subtracting" the symbol range if the decoded bin is 1 simply involves clearing that bit. // //As a result, the required bins are simply the next-most-significant bits of m_uiValue //(m_uiValue is stored MSB-aligned in a 16-bit buffer - hence the shift of 15) // // m_uiValue = |0|V|V|V|V|V|V|V|V|B|B|B|B|B|B|B| (V = usable bit, B = potential buffered bit (buffer refills when m_bitsNeeded >= 0)) // const UInt newBins = (m_uiValue >> (15 - binsToRead)) & binMask; ruiBins = (ruiBins << binsToRead) | newBins; m_uiValue = (m_uiValue << binsToRead) & 0x7FFF; binsRemaining -= binsToRead; m_bitsNeeded += binsToRead; if (m_bitsNeeded >= 0) { m_uiValue |= m_pcTComBitstream->readByte() << m_bitsNeeded; m_bitsNeeded -= 8; } } #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(whichStat, numBins, Int(ruiBins)); #endif } Void TDecBinCABAC::decodeBinTrm( UInt& ruiBin ) { m_uiRange -= 2; UInt scaledRange = m_uiRange << 7; if( m_uiValue >= scaledRange ) { ruiBin = 1; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(STATS__CABAC_TRM_BITS, m_uiRange+2, 2, ruiBin); TComCodingStatistics::IncrementStatisticEP(STATS__BYTE_ALIGNMENT_BITS, -m_bitsNeeded, 0); #endif } else { ruiBin = 0; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::UpdateCABACStat(STATS__CABAC_TRM_BITS, m_uiRange+2, m_uiRange, ruiBin); #endif if ( scaledRange < ( 256 << 7 ) ) { m_uiRange = scaledRange >> 6; m_uiValue += m_uiValue; if ( ++m_bitsNeeded == 0 ) { m_bitsNeeded = -8; m_uiValue += m_pcTComBitstream->readByte(); } } } } /** Read a PCM code. * \param uiLength code bit-depth * \param ruiCode pointer to PCM code value * \returns Void */ Void TDecBinCABAC::xReadPCMCode(UInt uiLength, UInt& ruiCode) { assert ( uiLength > 0 ); m_pcTComBitstream->read (uiLength, ruiCode); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(STATS__CABAC_PCM_CODE_BITS, uiLength, ruiCode); #endif } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecBinCoderCABAC.h000066400000000000000000000071511442026013100215030ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecBinCoderCABAC.h \brief binary entropy decoder of CABAC */ #ifndef __TDECBINCODERCABAC__ #define __TDECBINCODERCABAC__ #include "TLibCommon/TComCABACTables.h" #include "TDecBinCoder.h" //! \ingroup TLibDecoder //! \{ class TDecBinCABAC : public TDecBinIf { public: TDecBinCABAC (); virtual ~TDecBinCABAC(); Void init ( TComInputBitstream* pcTComBitstream ); Void uninit (); Void start (); Void finish (); #if RExt__DECODER_DEBUG_BIT_STATISTICS Void decodeBin ( UInt& ruiBin, ContextModel& rcCtxModel, const class TComCodingStatisticsClassType &whichStat ); Void decodeBinEP ( UInt& ruiBin , const class TComCodingStatisticsClassType &whichStat ); Void decodeBinsEP ( UInt& ruiBin, Int numBins , const class TComCodingStatisticsClassType &whichStat ); Void decodeAlignedBinsEP( UInt& ruiBins, Int numBins , const class TComCodingStatisticsClassType &whichStat ); #else Void decodeBin ( UInt& ruiBin, ContextModel& rcCtxModel ); Void decodeBinEP ( UInt& ruiBin ); Void decodeBinsEP ( UInt& ruiBin, Int numBins ); Void decodeAlignedBinsEP( UInt& ruiBins, Int numBins ); #endif Void align (); Void decodeBinTrm ( UInt& ruiBin ); Void xReadPCMCode ( UInt uiLength, UInt& ruiCode ); Void copyState ( const TDecBinIf* pcTDecBinIf ); TDecBinCABAC* getTDecBinCABAC() { return this; } const TDecBinCABAC* getTDecBinCABAC() const { return this; } private: TComInputBitstream* m_pcTComBitstream; UInt m_uiRange; UInt m_uiValue; Int m_bitsNeeded; }; //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecCAVLC.cpp000066400000000000000000002441631442026013100204750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecCAVLC.cpp \brief CAVLC decoder class */ #include "TDecCAVLC.h" #include "SEIread.h" #include "TDecSlice.h" #include "TLibCommon/TComChromaFormat.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" #endif #include "TDecConformance.h" //! \ingroup TLibDecoder //! \{ #if ENC_DEC_TRACE #if MCTS_EXTRACTION Void xTraceVPSHeaderDec () #else Void xTraceVPSHeader() #endif { fprintf( g_hTrace, "=========== Video Parameter Set ===========\n" ); } #if MCTS_EXTRACTION Void xTraceSPSHeaderDec() #else Void xTraceSPSHeader() #endif { fprintf( g_hTrace, "=========== Sequence Parameter Set ===========\n" ); } #if MCTS_EXTRACTION Void xTracePPSHeaderDec() #else Void xTracePPSHeader() #endif { fprintf( g_hTrace, "=========== Picture Parameter Set ===========\n"); } #if MCTS_EXTRACTION Void xTraceSliceHeaderDec() #else Void xTraceSliceHeader() #endif { fprintf( g_hTrace, "=========== Slice ===========\n"); } #endif // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TDecCavlc::TDecCavlc() { } TDecCavlc::~TDecCavlc() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TDecCavlc::parseShortTermRefPicSet( TComSPS* sps, TComReferencePictureSet* rps, Int idx ) { UInt code; UInt interRPSPred; if (idx > 0) { READ_FLAG(interRPSPred, "inter_ref_pic_set_prediction_flag"); rps->setInterRPSPrediction(interRPSPred); } else { interRPSPred = false; rps->setInterRPSPrediction(false); } if (interRPSPred) { UInt bit; if(idx == sps->getRPSList()->getNumberOfReferencePictureSets()) { READ_UVLC(code, "delta_idx_minus1" ); // delta index of the Reference Picture Set used for prediction minus 1 } else { code = 0; } #if MCTS_EXTRACTION rps->setDeltaRIdxMinus1(code); // when -1, reference picture set explicitly signalled in slice header, otherwise identify the PPS RPS; added for MCTS extraction #endif assert(code <= idx-1); // delta_idx_minus1 shall not be larger than idx-1, otherwise we will predict from a negative row position that does not exist. When idx equals 0 there is no legal value and interRPSPred must be zero. See J0185-r2 Int rIdx = idx - 1 - code; assert (rIdx <= idx-1 && rIdx >= 0); // Made assert tighter; if rIdx = idx then prediction is done from itself. rIdx must belong to range 0, idx-1, inclusive, see J0185-r2 TComReferencePictureSet* rpsRef = sps->getRPSList()->getReferencePictureSet(rIdx); Int k = 0, k0 = 0, k1 = 0; READ_CODE(1, bit, "delta_rps_sign"); // delta_RPS_sign READ_UVLC(code, "abs_delta_rps_minus1"); // absolute delta RPS minus 1 Int deltaRPS = (1 - 2 * bit) * (code + 1); // delta_RPS #if MCTS_EXTRACTION rps->setDeltaRPS(deltaRPS); // when -1, reference picture set explicitly signalled in slice header, otherwise identify the PPS RPS; added for MCTS extraction #endif for(Int j=0 ; j <= rpsRef->getNumberOfPictures(); j++) { READ_CODE(1, bit, "used_by_curr_pic_flag" ); //first bit is "1" if Idc is 1 Int refIdc = bit; if (refIdc == 0) { READ_CODE(1, bit, "use_delta_flag" ); //second bit is "1" if Idc is 2, "0" otherwise. refIdc = bit<<1; //second bit is "1" if refIdc is 2, "0" if refIdc = 0. } if (refIdc == 1 || refIdc == 2) { Int deltaPOC = deltaRPS + ((j < rpsRef->getNumberOfPictures())? rpsRef->getDeltaPOC(j) : 0); rps->setDeltaPOC(k, deltaPOC); rps->setUsed(k, (refIdc == 1)); if (deltaPOC < 0) { k0++; } else { k1++; } k++; } rps->setRefIdc(j,refIdc); } rps->setNumRefIdc(rpsRef->getNumberOfPictures()+1); rps->setNumberOfPictures(k); rps->setNumberOfNegativePictures(k0); rps->setNumberOfPositivePictures(k1); rps->sortDeltaPOC(); } else { READ_UVLC(code, "num_negative_pics"); rps->setNumberOfNegativePictures(code); READ_UVLC(code, "num_positive_pics"); rps->setNumberOfPositivePictures(code); Int prev = 0; Int poc; for(Int j=0 ; j < rps->getNumberOfNegativePictures(); j++) { READ_UVLC(code, "delta_poc_s0_minus1"); poc = prev-code-1; prev = poc; rps->setDeltaPOC(j,poc); READ_FLAG(code, "used_by_curr_pic_s0_flag"); rps->setUsed(j,code); } prev = 0; for(Int j=rps->getNumberOfNegativePictures(); j < rps->getNumberOfNegativePictures()+rps->getNumberOfPositivePictures(); j++) { READ_UVLC(code, "delta_poc_s1_minus1"); poc = prev+code+1; prev = poc; rps->setDeltaPOC(j,poc); READ_FLAG(code, "used_by_curr_pic_s1_flag"); rps->setUsed(j,code); } rps->setNumberOfPictures(rps->getNumberOfNegativePictures()+rps->getNumberOfPositivePictures()); } #if PRINT_RPS_INFO rps->printDeltaPOC(); #endif } Void TDecCavlc::parsePPS(TComPPS* pcPPS) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTracePPSHeaderDec (); #else xTracePPSHeader(); #endif #endif UInt uiCode; Int iCode; READ_UVLC_CHK( uiCode, "pps_pic_parameter_set_id", 0, 63); assert(uiCode <= 63); pcPPS->setPPSId (uiCode); READ_UVLC_CHK( uiCode, "pps_seq_parameter_set_id", 0, 15); assert(uiCode <= 15); pcPPS->setSPSId (uiCode); READ_FLAG( uiCode, "dependent_slice_segments_enabled_flag" ); pcPPS->setDependentSliceSegmentsEnabledFlag ( uiCode == 1 ); READ_FLAG( uiCode, "output_flag_present_flag" ); pcPPS->setOutputFlagPresentFlag( uiCode==1 ); READ_CODE(3, uiCode, "num_extra_slice_header_bits"); pcPPS->setNumExtraSliceHeaderBits(uiCode); READ_FLAG( uiCode, "sign_data_hiding_enabled_flag" ); pcPPS->setSignDataHidingEnabledFlag( uiCode ); READ_FLAG( uiCode, "cabac_init_present_flag" ); pcPPS->setCabacInitPresentFlag( uiCode ? true : false ); READ_UVLC_CHK(uiCode, "num_ref_idx_l0_default_active_minus1", 0, 14); assert(uiCode <= 14); pcPPS->setNumRefIdxL0DefaultActive(uiCode+1); READ_UVLC_CHK(uiCode, "num_ref_idx_l1_default_active_minus1", 0, 14); assert(uiCode <= 14); pcPPS->setNumRefIdxL1DefaultActive(uiCode+1); READ_SVLC_CHK(iCode, "init_qp_minus26", std::numeric_limits::min(), 25 ); pcPPS->setPicInitQPMinus26(iCode); READ_FLAG( uiCode, "constrained_intra_pred_flag" ); pcPPS->setConstrainedIntraPred( uiCode ? true : false ); READ_FLAG( uiCode, "transform_skip_enabled_flag" ); pcPPS->setUseTransformSkip ( uiCode ? true : false ); READ_FLAG( uiCode, "cu_qp_delta_enabled_flag" ); pcPPS->setUseDQP( uiCode ? true : false ); if( pcPPS->getUseDQP() ) { READ_UVLC( uiCode, "diff_cu_qp_delta_depth" ); pcPPS->setMaxCuDQPDepth( uiCode ); } else { pcPPS->setMaxCuDQPDepth( 0 ); } READ_SVLC_CHK( iCode, "pps_cb_qp_offset", -12, 12); pcPPS->setQpOffset(COMPONENT_Cb, iCode); assert( pcPPS->getQpOffset(COMPONENT_Cb) >= -12 ); assert( pcPPS->getQpOffset(COMPONENT_Cb) <= 12 ); READ_SVLC_CHK( iCode, "pps_cr_qp_offset", -12, 12); pcPPS->setQpOffset(COMPONENT_Cr, iCode); assert( pcPPS->getQpOffset(COMPONENT_Cr) >= -12 ); assert( pcPPS->getQpOffset(COMPONENT_Cr) <= 12 ); assert(MAX_NUM_COMPONENT<=3); READ_FLAG( uiCode, "pps_slice_chroma_qp_offsets_present_flag" ); pcPPS->setSliceChromaQpFlag( uiCode ? true : false ); READ_FLAG( uiCode, "weighted_pred_flag" ); // Use of Weighting Prediction (P_SLICE) pcPPS->setUseWP( uiCode==1 ); READ_FLAG( uiCode, "weighted_bipred_flag" ); // Use of Bi-Directional Weighting Prediction (B_SLICE) pcPPS->setWPBiPred( uiCode==1 ); READ_FLAG( uiCode, "transquant_bypass_enabled_flag"); pcPPS->setTransquantBypassEnabledFlag(uiCode ? true : false); READ_FLAG( uiCode, "tiles_enabled_flag" ); pcPPS->setTilesEnabledFlag ( uiCode == 1 ); READ_FLAG( uiCode, "entropy_coding_sync_enabled_flag" ); pcPPS->setEntropyCodingSyncEnabledFlag( uiCode == 1 ); if( pcPPS->getTilesEnabledFlag() ) { READ_UVLC ( uiCode, "num_tile_columns_minus1" ); pcPPS->setNumTileColumnsMinus1( uiCode ); READ_UVLC ( uiCode, "num_tile_rows_minus1" ); pcPPS->setNumTileRowsMinus1( uiCode ); READ_FLAG ( uiCode, "uniform_spacing_flag" ); pcPPS->setTileUniformSpacingFlag( uiCode == 1 ); const UInt tileColumnsMinus1 = pcPPS->getNumTileColumnsMinus1(); const UInt tileRowsMinus1 = pcPPS->getNumTileRowsMinus1(); if ( !pcPPS->getTileUniformSpacingFlag()) { if (tileColumnsMinus1 > 0) { std::vector columnWidth(tileColumnsMinus1); for(UInt i = 0; i < tileColumnsMinus1; i++) { READ_UVLC( uiCode, "column_width_minus1" ); columnWidth[i] = uiCode+1; } pcPPS->setTileColumnWidth(columnWidth); } if (tileRowsMinus1 > 0) { std::vector rowHeight (tileRowsMinus1); for(UInt i = 0; i < tileRowsMinus1; i++) { READ_UVLC( uiCode, "row_height_minus1" ); rowHeight[i] = uiCode + 1; } pcPPS->setTileRowHeight(rowHeight); } } assert ((tileColumnsMinus1 + tileRowsMinus1) != 0); READ_FLAG ( uiCode, "loop_filter_across_tiles_enabled_flag" ); pcPPS->setLoopFilterAcrossTilesEnabledFlag( uiCode ? true : false ); } READ_FLAG( uiCode, "pps_loop_filter_across_slices_enabled_flag" ); pcPPS->setLoopFilterAcrossSlicesEnabledFlag( uiCode ? true : false ); READ_FLAG( uiCode, "deblocking_filter_control_present_flag" ); pcPPS->setDeblockingFilterControlPresentFlag( uiCode ? true : false ); if(pcPPS->getDeblockingFilterControlPresentFlag()) { READ_FLAG( uiCode, "deblocking_filter_override_enabled_flag" ); pcPPS->setDeblockingFilterOverrideEnabledFlag( uiCode ? true : false ); READ_FLAG( uiCode, "pps_deblocking_filter_disabled_flag" ); pcPPS->setPPSDeblockingFilterDisabledFlag(uiCode ? true : false ); if(!pcPPS->getPPSDeblockingFilterDisabledFlag()) { READ_SVLC ( iCode, "pps_beta_offset_div2" ); pcPPS->setDeblockingFilterBetaOffsetDiv2( iCode ); READ_SVLC ( iCode, "pps_tc_offset_div2" ); pcPPS->setDeblockingFilterTcOffsetDiv2( iCode ); } } READ_FLAG( uiCode, "pps_scaling_list_data_present_flag" ); pcPPS->setScalingListPresentFlag( uiCode ? true : false ); if(pcPPS->getScalingListPresentFlag ()) { parseScalingList( &(pcPPS->getScalingList()) ); } READ_FLAG( uiCode, "lists_modification_present_flag"); pcPPS->setListsModificationPresentFlag(uiCode); READ_UVLC( uiCode, "log2_parallel_merge_level_minus2"); pcPPS->setLog2ParallelMergeLevelMinus2 (uiCode); READ_FLAG( uiCode, "slice_segment_header_extension_present_flag"); pcPPS->setSliceHeaderExtensionPresentFlag(uiCode); READ_FLAG( uiCode, "pps_extension_present_flag"); if (uiCode) { #if ENC_DEC_TRACE || RExt__DECODER_DEBUG_BIT_STATISTICS static const TChar *syntaxStrings[]={ "pps_range_extension_flag", "pps_multilayer_extension_flag", "pps_extension_6bits[0]", "pps_extension_6bits[1]", "pps_extension_6bits[2]", "pps_extension_6bits[3]", "pps_extension_6bits[4]", "pps_extension_6bits[5]" }; #endif Bool pps_extension_flags[NUM_PPS_EXTENSION_FLAGS]; for(Int i=0; igetPpsRangeExtension(); assert(!bSkipTrailingExtensionBits); if (pcPPS->getUseTransformSkip()) { READ_UVLC( uiCode, "log2_max_transform_skip_block_size_minus2"); ppsRangeExtension.setLog2MaxTransformSkipBlockSize(uiCode+2); } READ_FLAG( uiCode, "cross_component_prediction_enabled_flag"); ppsRangeExtension.setCrossComponentPredictionEnabledFlag(uiCode != 0); READ_FLAG( uiCode, "chroma_qp_offset_list_enabled_flag"); if (uiCode == 0) { ppsRangeExtension.clearChromaQpOffsetList(); ppsRangeExtension.setDiffCuChromaQpOffsetDepth(0); } else { READ_UVLC(uiCode, "diff_cu_chroma_qp_offset_depth"); ppsRangeExtension.setDiffCuChromaQpOffsetDepth(uiCode); UInt tableSizeMinus1 = 0; READ_UVLC_CHK(tableSizeMinus1, "chroma_qp_offset_list_len_minus1", 0, MAX_QP_OFFSET_LIST_SIZE-1); assert(tableSizeMinus1 < MAX_QP_OFFSET_LIST_SIZE); for (Int cuChromaQpOffsetIdx = 0; cuChromaQpOffsetIdx <= (tableSizeMinus1); cuChromaQpOffsetIdx++) { Int cbOffset; Int crOffset; READ_SVLC_CHK(cbOffset, "cb_qp_offset_list[i]", -12, 12); assert(cbOffset >= -12 && cbOffset <= 12); READ_SVLC_CHK(crOffset, "cr_qp_offset_list[i]", -12, 12); assert(crOffset >= -12 && crOffset <= 12); // table uses +1 for index (see comment inside the function) ppsRangeExtension.setChromaQpOffsetListEntry(cuChromaQpOffsetIdx+1, cbOffset, crOffset); } assert(ppsRangeExtension.getChromaQpOffsetListLen() == tableSizeMinus1 + 1); } READ_UVLC( uiCode, "log2_sao_offset_scale_luma"); ppsRangeExtension.setLog2SaoOffsetScale(CHANNEL_TYPE_LUMA, uiCode); READ_UVLC( uiCode, "log2_sao_offset_scale_chroma"); ppsRangeExtension.setLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA, uiCode); } break; default: bSkipTrailingExtensionBits=true; break; } } } if (bSkipTrailingExtensionBits) { while ( xMoreRbspData() ) { READ_FLAG( uiCode, "pps_extension_data_flag"); } } } xReadRbspTrailingBits(); } Void TDecCavlc::parseVUI(TComVUI* pcVUI, TComSPS *pcSPS) { #if ENC_DEC_TRACE fprintf( g_hTrace, "----------- vui_parameters -----------\n"); #endif UInt uiCode; READ_FLAG( uiCode, "aspect_ratio_info_present_flag"); pcVUI->setAspectRatioInfoPresentFlag(uiCode); if (pcVUI->getAspectRatioInfoPresentFlag()) { READ_CODE(8, uiCode, "aspect_ratio_idc"); pcVUI->setAspectRatioIdc(uiCode); if (pcVUI->getAspectRatioIdc() == 255) { READ_CODE(16, uiCode, "sar_width"); pcVUI->setSarWidth(uiCode); READ_CODE(16, uiCode, "sar_height"); pcVUI->setSarHeight(uiCode); } } READ_FLAG( uiCode, "overscan_info_present_flag"); pcVUI->setOverscanInfoPresentFlag(uiCode); if (pcVUI->getOverscanInfoPresentFlag()) { READ_FLAG( uiCode, "overscan_appropriate_flag"); pcVUI->setOverscanAppropriateFlag(uiCode); } READ_FLAG( uiCode, "video_signal_type_present_flag"); pcVUI->setVideoSignalTypePresentFlag(uiCode); if (pcVUI->getVideoSignalTypePresentFlag()) { READ_CODE(3, uiCode, "video_format"); pcVUI->setVideoFormat(uiCode); READ_FLAG( uiCode, "video_full_range_flag"); pcVUI->setVideoFullRangeFlag(uiCode); READ_FLAG( uiCode, "colour_description_present_flag"); pcVUI->setColourDescriptionPresentFlag(uiCode); if (pcVUI->getColourDescriptionPresentFlag()) { READ_CODE(8, uiCode, "colour_primaries"); pcVUI->setColourPrimaries(uiCode); READ_CODE(8, uiCode, "transfer_characteristics"); pcVUI->setTransferCharacteristics(uiCode); READ_CODE(8, uiCode, "matrix_coeffs"); pcVUI->setMatrixCoefficients(uiCode); } } READ_FLAG( uiCode, "chroma_loc_info_present_flag"); pcVUI->setChromaLocInfoPresentFlag(uiCode); if (pcVUI->getChromaLocInfoPresentFlag()) { READ_UVLC( uiCode, "chroma_sample_loc_type_top_field" ); pcVUI->setChromaSampleLocTypeTopField(uiCode); READ_UVLC( uiCode, "chroma_sample_loc_type_bottom_field" ); pcVUI->setChromaSampleLocTypeBottomField(uiCode); } READ_FLAG( uiCode, "neutral_chroma_indication_flag"); pcVUI->setNeutralChromaIndicationFlag(uiCode); READ_FLAG( uiCode, "field_seq_flag"); pcVUI->setFieldSeqFlag(uiCode); READ_FLAG(uiCode, "frame_field_info_present_flag"); pcVUI->setFrameFieldInfoPresentFlag(uiCode); READ_FLAG( uiCode, "default_display_window_flag"); if (uiCode != 0) { Window &defDisp = pcVUI->getDefaultDisplayWindow(); READ_UVLC( uiCode, "def_disp_win_left_offset" ); defDisp.setWindowLeftOffset ( uiCode * TComSPS::getWinUnitX( pcSPS->getChromaFormatIdc()) ); READ_UVLC( uiCode, "def_disp_win_right_offset" ); defDisp.setWindowRightOffset ( uiCode * TComSPS::getWinUnitX( pcSPS->getChromaFormatIdc()) ); READ_UVLC( uiCode, "def_disp_win_top_offset" ); defDisp.setWindowTopOffset ( uiCode * TComSPS::getWinUnitY( pcSPS->getChromaFormatIdc()) ); READ_UVLC( uiCode, "def_disp_win_bottom_offset" ); defDisp.setWindowBottomOffset( uiCode * TComSPS::getWinUnitY( pcSPS->getChromaFormatIdc()) ); } TimingInfo *timingInfo = pcVUI->getTimingInfo(); READ_FLAG( uiCode, "vui_timing_info_present_flag"); timingInfo->setTimingInfoPresentFlag (uiCode ? true : false); if(timingInfo->getTimingInfoPresentFlag()) { READ_CODE( 32, uiCode, "vui_num_units_in_tick"); timingInfo->setNumUnitsInTick (uiCode); READ_CODE( 32, uiCode, "vui_time_scale"); timingInfo->setTimeScale (uiCode); READ_FLAG( uiCode, "vui_poc_proportional_to_timing_flag"); timingInfo->setPocProportionalToTimingFlag(uiCode ? true : false); if(timingInfo->getPocProportionalToTimingFlag()) { READ_UVLC( uiCode, "vui_num_ticks_poc_diff_one_minus1"); timingInfo->setNumTicksPocDiffOneMinus1 (uiCode); } READ_FLAG( uiCode, "vui_hrd_parameters_present_flag"); pcVUI->setHrdParametersPresentFlag(uiCode); if( pcVUI->getHrdParametersPresentFlag() ) { parseHrdParameters( pcVUI->getHrdParameters(), 1, pcSPS->getMaxTLayers() - 1 ); } } READ_FLAG( uiCode, "bitstream_restriction_flag"); pcVUI->setBitstreamRestrictionFlag(uiCode); if (pcVUI->getBitstreamRestrictionFlag()) { READ_FLAG( uiCode, "tiles_fixed_structure_flag"); pcVUI->setTilesFixedStructureFlag(uiCode); READ_FLAG( uiCode, "motion_vectors_over_pic_boundaries_flag"); pcVUI->setMotionVectorsOverPicBoundariesFlag(uiCode); READ_FLAG( uiCode, "restricted_ref_pic_lists_flag"); pcVUI->setRestrictedRefPicListsFlag(uiCode); READ_UVLC( uiCode, "min_spatial_segmentation_idc"); pcVUI->setMinSpatialSegmentationIdc(uiCode); assert(uiCode < 4096); READ_UVLC( uiCode, "max_bytes_per_pic_denom" ); pcVUI->setMaxBytesPerPicDenom(uiCode); READ_UVLC( uiCode, "max_bits_per_min_cu_denom" ); pcVUI->setMaxBitsPerMinCuDenom(uiCode); READ_UVLC( uiCode, "log2_max_mv_length_horizontal" ); pcVUI->setLog2MaxMvLengthHorizontal(uiCode); READ_UVLC( uiCode, "log2_max_mv_length_vertical" ); pcVUI->setLog2MaxMvLengthVertical(uiCode); } } Void TDecCavlc::parseHrdParameters(TComHRD *hrd, Bool commonInfPresentFlag, UInt maxNumSubLayersMinus1) { UInt uiCode; if( commonInfPresentFlag ) { READ_FLAG( uiCode, "nal_hrd_parameters_present_flag" ); hrd->setNalHrdParametersPresentFlag( uiCode == 1 ? true : false ); READ_FLAG( uiCode, "vcl_hrd_parameters_present_flag" ); hrd->setVclHrdParametersPresentFlag( uiCode == 1 ? true : false ); if( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) { READ_FLAG( uiCode, "sub_pic_hrd_params_present_flag" ); hrd->setSubPicCpbParamsPresentFlag( uiCode == 1 ? true : false ); if( hrd->getSubPicCpbParamsPresentFlag() ) { READ_CODE( 8, uiCode, "tick_divisor_minus2" ); hrd->setTickDivisorMinus2( uiCode ); READ_CODE( 5, uiCode, "du_cpb_removal_delay_increment_length_minus1" ); hrd->setDuCpbRemovalDelayLengthMinus1( uiCode ); READ_FLAG( uiCode, "sub_pic_cpb_params_in_pic_timing_sei_flag" ); hrd->setSubPicCpbParamsInPicTimingSEIFlag( uiCode == 1 ? true : false ); READ_CODE( 5, uiCode, "dpb_output_delay_du_length_minus1" ); hrd->setDpbOutputDelayDuLengthMinus1( uiCode ); } READ_CODE( 4, uiCode, "bit_rate_scale" ); hrd->setBitRateScale( uiCode ); READ_CODE( 4, uiCode, "cpb_size_scale" ); hrd->setCpbSizeScale( uiCode ); if( hrd->getSubPicCpbParamsPresentFlag() ) { READ_CODE( 4, uiCode, "cpb_size_du_scale" ); hrd->setDuCpbSizeScale( uiCode ); } READ_CODE( 5, uiCode, "initial_cpb_removal_delay_length_minus1" ); hrd->setInitialCpbRemovalDelayLengthMinus1( uiCode ); READ_CODE( 5, uiCode, "au_cpb_removal_delay_length_minus1" ); hrd->setCpbRemovalDelayLengthMinus1( uiCode ); READ_CODE( 5, uiCode, "dpb_output_delay_length_minus1" ); hrd->setDpbOutputDelayLengthMinus1( uiCode ); } } Int i, j, nalOrVcl; for( i = 0; i <= maxNumSubLayersMinus1; i ++ ) { READ_FLAG( uiCode, "fixed_pic_rate_general_flag" ); hrd->setFixedPicRateFlag( i, uiCode == 1 ? true : false ); if( !hrd->getFixedPicRateFlag( i ) ) { READ_FLAG( uiCode, "fixed_pic_rate_within_cvs_flag" ); hrd->setFixedPicRateWithinCvsFlag( i, uiCode == 1 ? true : false ); } else { hrd->setFixedPicRateWithinCvsFlag( i, true ); } hrd->setLowDelayHrdFlag( i, 0 ); // Infered to be 0 when not present hrd->setCpbCntMinus1 ( i, 0 ); // Infered to be 0 when not present if( hrd->getFixedPicRateWithinCvsFlag( i ) ) { READ_UVLC( uiCode, "elemental_duration_in_tc_minus1" ); hrd->setPicDurationInTcMinus1( i, uiCode ); } else { READ_FLAG( uiCode, "low_delay_hrd_flag" ); hrd->setLowDelayHrdFlag( i, uiCode == 1 ? true : false ); } if (!hrd->getLowDelayHrdFlag( i )) { READ_UVLC( uiCode, "cpb_cnt_minus1" ); hrd->setCpbCntMinus1( i, uiCode ); } for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) || ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) ) { for( j = 0; j <= ( hrd->getCpbCntMinus1( i ) ); j ++ ) { READ_UVLC( uiCode, "bit_rate_value_minus1" ); hrd->setBitRateValueMinus1( i, j, nalOrVcl, uiCode ); READ_UVLC( uiCode, "cpb_size_value_minus1" ); hrd->setCpbSizeValueMinus1( i, j, nalOrVcl, uiCode ); if( hrd->getSubPicCpbParamsPresentFlag() ) { READ_UVLC( uiCode, "cpb_size_du_value_minus1" ); hrd->setDuCpbSizeValueMinus1( i, j, nalOrVcl, uiCode ); READ_UVLC( uiCode, "bit_rate_du_value_minus1" ); hrd->setDuBitRateValueMinus1( i, j, nalOrVcl, uiCode ); } READ_FLAG( uiCode, "cbr_flag" ); hrd->setCbrFlag( i, j, nalOrVcl, uiCode == 1 ? true : false ); } } } } } Void TDecCavlc::parseSPS(TComSPS* pcSPS) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceSPSHeaderDec (); #else xTraceSPSHeader (); #endif #endif UInt uiCode; READ_CODE( 4, uiCode, "sps_video_parameter_set_id"); pcSPS->setVPSId ( uiCode ); READ_CODE_CHK( 3, uiCode, "sps_max_sub_layers_minus1", 0, 6 ); pcSPS->setMaxTLayers ( uiCode+1 ); assert(uiCode <= 6); READ_FLAG( uiCode, "sps_temporal_id_nesting_flag" ); pcSPS->setTemporalIdNestingFlag ( uiCode > 0 ? true : false ); if ( pcSPS->getMaxTLayers() == 1 ) { // sps_temporal_id_nesting_flag must be 1 when sps_max_sub_layers_minus1 is 0 TDecConformanceCheck::checkRange(uiCode, "sps_temporal_id_nesting_flag", 1U, 1U); assert( uiCode == 1 ); } parsePTL(pcSPS->getPTL(), 1, pcSPS->getMaxTLayers() - 1); READ_UVLC_CHK( uiCode, "sps_seq_parameter_set_id", 0, 15 ); pcSPS->setSPSId( uiCode ); assert(uiCode <= 15); READ_UVLC_CHK( uiCode, "chroma_format_idc", 0, 3 ); pcSPS->setChromaFormatIdc( ChromaFormat(uiCode) ); assert(uiCode <= 3); if( pcSPS->getChromaFormatIdc() == CHROMA_444 ) { READ_FLAG_CHK( uiCode, "separate_colour_plane_flag", 0, 0); assert(uiCode == 0); } // pic_width_in_luma_samples and pic_height_in_luma_samples needs conformance checking - multiples of MinCbSizeY READ_UVLC_CHK ( uiCode, "pic_width_in_luma_samples", 1, std::numeric_limits::max() ); pcSPS->setPicWidthInLumaSamples ( uiCode ); READ_UVLC_CHK ( uiCode, "pic_height_in_luma_samples", 1, std::numeric_limits::max() ); pcSPS->setPicHeightInLumaSamples( uiCode ); READ_FLAG( uiCode, "conformance_window_flag"); if (uiCode != 0) { Window &conf = pcSPS->getConformanceWindow(); const UInt subWidthC = TComSPS::getWinUnitX( pcSPS->getChromaFormatIdc() ); const UInt subHeightC = TComSPS::getWinUnitY( pcSPS->getChromaFormatIdc() ); READ_UVLC( uiCode, "conf_win_left_offset" ); conf.setWindowLeftOffset ( uiCode * subWidthC ); READ_UVLC( uiCode, "conf_win_right_offset" ); conf.setWindowRightOffset ( uiCode * subWidthC ); READ_UVLC( uiCode, "conf_win_top_offset" ); conf.setWindowTopOffset ( uiCode * subHeightC ); READ_UVLC( uiCode, "conf_win_bottom_offset" ); conf.setWindowBottomOffset( uiCode * subHeightC ); TDecConformanceCheck::checkRange(conf.getWindowLeftOffset()+conf.getWindowRightOffset(), "conformance window width in pixels", 0, pcSPS->getPicWidthInLumaSamples()-1); } READ_UVLC_CHK( uiCode, "bit_depth_luma_minus8", 0, 8 ); assert(uiCode <= 8); #if O0043_BEST_EFFORT_DECODING pcSPS->setStreamBitDepth(CHANNEL_TYPE_LUMA, 8 + uiCode); const UInt forceDecodeBitDepth = pcSPS->getForceDecodeBitDepth(); if (forceDecodeBitDepth != 0) { uiCode = forceDecodeBitDepth - 8; } assert(uiCode <= 8); #endif pcSPS->setBitDepth(CHANNEL_TYPE_LUMA, 8 + uiCode); #if O0043_BEST_EFFORT_DECODING pcSPS->setQpBDOffset(CHANNEL_TYPE_LUMA, (Int) (6*(pcSPS->getStreamBitDepth(CHANNEL_TYPE_LUMA)-8)) ); #else pcSPS->setQpBDOffset(CHANNEL_TYPE_LUMA, (Int) (6*uiCode) ); #endif READ_UVLC_CHK( uiCode, "bit_depth_chroma_minus8", 0, 8 ); assert(uiCode <= 8); #if O0043_BEST_EFFORT_DECODING pcSPS->setStreamBitDepth(CHANNEL_TYPE_CHROMA, 8 + uiCode); if (forceDecodeBitDepth != 0) { uiCode = forceDecodeBitDepth - 8; } assert(uiCode <= 8); #endif pcSPS->setBitDepth(CHANNEL_TYPE_CHROMA, 8 + uiCode); #if O0043_BEST_EFFORT_DECODING pcSPS->setQpBDOffset(CHANNEL_TYPE_CHROMA, (Int) (6*(pcSPS->getStreamBitDepth(CHANNEL_TYPE_CHROMA)-8)) ); #else pcSPS->setQpBDOffset(CHANNEL_TYPE_CHROMA, (Int) (6*uiCode) ); #endif READ_UVLC_CHK( uiCode, "log2_max_pic_order_cnt_lsb_minus4", 0, 12 ); pcSPS->setBitsForPOC( 4 + uiCode ); UInt subLayerOrderingInfoPresentFlag; READ_FLAG(subLayerOrderingInfoPresentFlag, "sps_sub_layer_ordering_info_present_flag"); for(UInt i=0; i <= pcSPS->getMaxTLayers()-1; i++) { READ_UVLC ( uiCode, "sps_max_dec_pic_buffering_minus1[i]"); pcSPS->setMaxDecPicBuffering( uiCode + 1, i); READ_UVLC ( uiCode, "sps_max_num_reorder_pics[i]" ); pcSPS->setNumReorderPics(uiCode, i); READ_UVLC ( uiCode, "sps_max_latency_increase_plus1[i]"); pcSPS->setMaxLatencyIncreasePlus1( uiCode, i ); if (!subLayerOrderingInfoPresentFlag) { for (i++; i <= pcSPS->getMaxTLayers()-1; i++) { pcSPS->setMaxDecPicBuffering(pcSPS->getMaxDecPicBuffering(0), i); pcSPS->setNumReorderPics(pcSPS->getNumReorderPics(0), i); pcSPS->setMaxLatencyIncreasePlus1(pcSPS->getMaxLatencyIncreasePlus1(0), i); } break; } } const UInt maxLog2CtbSize = TDecConformanceCheck::getMaxLog2CtbSize(*(pcSPS->getPTL())); const UInt minLog2CtbSize = TDecConformanceCheck::getMinLog2CtbSize(*(pcSPS->getPTL())); READ_UVLC_CHK( uiCode, "log2_min_luma_coding_block_size_minus3", 0, maxLog2CtbSize-3 ); assert(uiCode <= maxLog2CtbSize-3); Int minCbLog2SizeY = uiCode + 3; pcSPS->setLog2MinCodingBlockSize(minCbLog2SizeY); // Difference + log2MinCUSize must be <= maxLog2CtbSize // Difference + log2MinCUSize must be >= minLog2CtbSize const UInt minLog2DiffMaxMinLumaCodingBlockSize = minLog2CtbSize < minCbLog2SizeY ? 0 : minLog2CtbSize - minCbLog2SizeY; const UInt maxLog2DiffMaxMinLumaCodingBlockSize = maxLog2CtbSize - minCbLog2SizeY; READ_UVLC_CHK( uiCode, "log2_diff_max_min_luma_coding_block_size", minLog2DiffMaxMinLumaCodingBlockSize, maxLog2DiffMaxMinLumaCodingBlockSize); assert(uiCode >= minLog2DiffMaxMinLumaCodingBlockSize && uiCode <= maxLog2DiffMaxMinLumaCodingBlockSize); pcSPS->setLog2DiffMaxMinCodingBlockSize(uiCode); const Int maxCUDepthDelta = uiCode; const Int ctbLog2SizeY = minCbLog2SizeY + maxCUDepthDelta; pcSPS->setMaxCUWidth ( 1<setMaxCUHeight ( 1<setQuadtreeTULog2MinSize( minTbLog2SizeY ); // log2_diff <= Min(CtbLog2SizeY, 5) - minTbLog2SizeY READ_UVLC_CHK( uiCode, "log2_diff_max_min_luma_transform_block_size", 0, min(5U, ctbLog2SizeY) - minTbLog2SizeY ); pcSPS->setQuadtreeTULog2MaxSize( uiCode + pcSPS->getQuadtreeTULog2MinSize() ); pcSPS->setMaxTrSize( 1<<(uiCode + pcSPS->getQuadtreeTULog2MinSize()) ); READ_UVLC_CHK( uiCode, "max_transform_hierarchy_depth_inter", 0, ctbLog2SizeY - minTbLog2SizeY); pcSPS->setQuadtreeTUMaxDepthInter( uiCode+1 ); READ_UVLC_CHK( uiCode, "max_transform_hierarchy_depth_intra", 0, ctbLog2SizeY - minTbLog2SizeY); pcSPS->setQuadtreeTUMaxDepthIntra( uiCode+1 ); Int addCuDepth = max (0, minCbLog2SizeY - (Int)pcSPS->getQuadtreeTULog2MinSize() ); pcSPS->setMaxTotalCUDepth( maxCUDepthDelta + addCuDepth + getMaxCUDepthOffset(pcSPS->getChromaFormatIdc(), pcSPS->getQuadtreeTULog2MinSize()) ); READ_FLAG( uiCode, "scaling_list_enabled_flag" ); pcSPS->setScalingListFlag ( uiCode ); if(pcSPS->getScalingListFlag()) { READ_FLAG( uiCode, "sps_scaling_list_data_present_flag" ); pcSPS->setScalingListPresentFlag ( uiCode ); if(pcSPS->getScalingListPresentFlag ()) { parseScalingList( &(pcSPS->getScalingList()) ); } } READ_FLAG( uiCode, "amp_enabled_flag" ); pcSPS->setUseAMP( uiCode ); READ_FLAG( uiCode, "sample_adaptive_offset_enabled_flag" ); pcSPS->setUseSAO ( uiCode ? true : false ); READ_FLAG( uiCode, "pcm_enabled_flag" ); pcSPS->setUsePCM( uiCode ? true : false ); if( pcSPS->getUsePCM() ) { #if O0043_BEST_EFFORT_DECODING READ_CODE_CHK( 4, uiCode, "pcm_sample_bit_depth_luma_minus1", 0, pcSPS->getStreamBitDepth(CHANNEL_TYPE_LUMA) ); pcSPS->setPCMBitDepth ( CHANNEL_TYPE_LUMA, 1 + uiCode ); READ_CODE_CHK( 4, uiCode, "pcm_sample_bit_depth_chroma_minus1", 0, pcSPS->getStreamBitDepth(CHANNEL_TYPE_LUMA) ); pcSPS->setPCMBitDepth ( CHANNEL_TYPE_CHROMA, 1 + uiCode ); #else READ_CODE_CHK( 4, uiCode, "pcm_sample_bit_depth_luma_minus1", 0, pcSPS->getBitDepth(CHANNEL_TYPE_LUMA) ); pcSPS->setPCMBitDepth ( CHANNEL_TYPE_LUMA, 1 + uiCode ); READ_CODE_CHK( 4, uiCode, "pcm_sample_bit_depth_chroma_minus1", 0, pcSPS->getBitDepth(CHANNEL_TYPE_CHROMA) ); pcSPS->setPCMBitDepth ( CHANNEL_TYPE_CHROMA, 1 + uiCode ); #endif READ_UVLC_CHK( uiCode, "log2_min_pcm_luma_coding_block_size_minus3", std::min(minCbLog2SizeY, 5 )-3, std::min(ctbLog2SizeY, 5)-3); const UInt log2MinIpcmCbSizeY = uiCode+3; pcSPS->setPCMLog2MinSize (log2MinIpcmCbSizeY); READ_UVLC_CHK( uiCode, "log2_diff_max_min_pcm_luma_coding_block_size", 0, (std::min(ctbLog2SizeY,5) - log2MinIpcmCbSizeY) ); pcSPS->setPCMLog2MaxSize ( uiCode+pcSPS->getPCMLog2MinSize() ); READ_FLAG( uiCode, "pcm_loop_filter_disable_flag" ); pcSPS->setPCMFilterDisableFlag ( uiCode ? true : false ); } READ_UVLC_CHK( uiCode, "num_short_term_ref_pic_sets", 0, 64 ); assert(uiCode <= 64); pcSPS->createRPSList(uiCode); TComRPSList* rpsList = pcSPS->getRPSList(); TComReferencePictureSet* rps; for(UInt i=0; i< rpsList->getNumberOfReferencePictureSets(); i++) { rps = rpsList->getReferencePictureSet(i); parseShortTermRefPicSet(pcSPS,rps,i); } READ_FLAG( uiCode, "long_term_ref_pics_present_flag" ); pcSPS->setLongTermRefsPresent(uiCode); if (pcSPS->getLongTermRefsPresent()) { READ_UVLC_CHK( uiCode, "num_long_term_ref_pics_sps", 0, 32 ); pcSPS->setNumLongTermRefPicSPS(uiCode); for (UInt k = 0; k < pcSPS->getNumLongTermRefPicSPS(); k++) { READ_CODE( pcSPS->getBitsForPOC(), uiCode, "lt_ref_pic_poc_lsb_sps" ); pcSPS->setLtRefPicPocLsbSps(k, uiCode); READ_FLAG( uiCode, "used_by_curr_pic_lt_sps_flag[i]"); pcSPS->setUsedByCurrPicLtSPSFlag(k, uiCode?1:0); } } READ_FLAG( uiCode, "sps_temporal_mvp_enabled_flag" ); pcSPS->setSPSTemporalMVPEnabledFlag(uiCode); READ_FLAG( uiCode, "strong_intra_smoothing_enable_flag" ); pcSPS->setUseStrongIntraSmoothing(uiCode); READ_FLAG( uiCode, "vui_parameters_present_flag" ); pcSPS->setVuiParametersPresentFlag(uiCode); if (pcSPS->getVuiParametersPresentFlag()) { parseVUI(pcSPS->getVuiParameters(), pcSPS); } READ_FLAG( uiCode, "sps_extension_present_flag"); if (uiCode) { #if ENC_DEC_TRACE || RExt__DECODER_DEBUG_BIT_STATISTICS static const TChar *syntaxStrings[]={ "sps_range_extension_flag", "sps_multilayer_extension_flag", "sps_extension_6bits[0]", "sps_extension_6bits[1]", "sps_extension_6bits[2]", "sps_extension_6bits[3]", "sps_extension_6bits[4]", "sps_extension_6bits[5]" }; #endif Bool sps_extension_flags[NUM_SPS_EXTENSION_FLAGS]; for(Int i=0; igetSpsRangeExtension(); READ_FLAG( uiCode, "transform_skip_rotation_enabled_flag"); spsRangeExtension.setTransformSkipRotationEnabledFlag(uiCode != 0); READ_FLAG( uiCode, "transform_skip_context_enabled_flag"); spsRangeExtension.setTransformSkipContextEnabledFlag (uiCode != 0); READ_FLAG( uiCode, "implicit_rdpcm_enabled_flag"); spsRangeExtension.setRdpcmEnabledFlag(RDPCM_SIGNAL_IMPLICIT, (uiCode != 0)); READ_FLAG( uiCode, "explicit_rdpcm_enabled_flag"); spsRangeExtension.setRdpcmEnabledFlag(RDPCM_SIGNAL_EXPLICIT, (uiCode != 0)); READ_FLAG( uiCode, "extended_precision_processing_flag"); spsRangeExtension.setExtendedPrecisionProcessingFlag (uiCode != 0); READ_FLAG( uiCode, "intra_smoothing_disabled_flag"); spsRangeExtension.setIntraSmoothingDisabledFlag (uiCode != 0); READ_FLAG( uiCode, "high_precision_offsets_enabled_flag"); spsRangeExtension.setHighPrecisionOffsetsEnabledFlag (uiCode != 0); READ_FLAG( uiCode, "persistent_rice_adaptation_enabled_flag"); spsRangeExtension.setPersistentRiceAdaptationEnabledFlag (uiCode != 0); READ_FLAG( uiCode, "cabac_bypass_alignment_enabled_flag"); spsRangeExtension.setCabacBypassAlignmentEnabledFlag (uiCode != 0); } break; default: bSkipTrailingExtensionBits=true; break; } } } if (bSkipTrailingExtensionBits) { while ( xMoreRbspData() ) { READ_FLAG( uiCode, "sps_extension_data_flag"); } } } xReadRbspTrailingBits(); } Void TDecCavlc::parseVPS(TComVPS* pcVPS) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceVPSHeaderDec (); #else xTraceVPSHeader(); #endif #endif UInt uiCode; READ_CODE( 4, uiCode, "vps_video_parameter_set_id" ); pcVPS->setVPSId( uiCode ); READ_FLAG( uiCode, "vps_base_layer_internal_flag" ); assert(uiCode == 1); READ_FLAG( uiCode, "vps_base_layer_available_flag" ); assert(uiCode == 1); READ_CODE( 6, uiCode, "vps_max_layers_minus1" ); READ_CODE( 3, uiCode, "vps_max_sub_layers_minus1" ); pcVPS->setMaxTLayers( uiCode + 1 ); assert(uiCode+1 <= MAX_TLAYER); READ_FLAG( uiCode, "vps_temporal_id_nesting_flag" ); pcVPS->setTemporalNestingFlag( uiCode ? true:false ); assert (pcVPS->getMaxTLayers()>1||pcVPS->getTemporalNestingFlag()); READ_CODE( 16, uiCode, "vps_reserved_0xffff_16bits" ); assert(uiCode == 0xffff); parsePTL ( pcVPS->getPTL(), true, pcVPS->getMaxTLayers()-1); UInt subLayerOrderingInfoPresentFlag; READ_FLAG(subLayerOrderingInfoPresentFlag, "vps_sub_layer_ordering_info_present_flag"); for(UInt i = 0; i <= pcVPS->getMaxTLayers()-1; i++) { READ_UVLC( uiCode, "vps_max_dec_pic_buffering_minus1[i]" ); pcVPS->setMaxDecPicBuffering( uiCode + 1, i ); READ_UVLC( uiCode, "vps_max_num_reorder_pics[i]" ); pcVPS->setNumReorderPics( uiCode, i ); READ_UVLC( uiCode, "vps_max_latency_increase_plus1[i]" ); pcVPS->setMaxLatencyIncrease( uiCode, i ); if (!subLayerOrderingInfoPresentFlag) { for (i++; i <= pcVPS->getMaxTLayers()-1; i++) { pcVPS->setMaxDecPicBuffering(pcVPS->getMaxDecPicBuffering(0), i); pcVPS->setNumReorderPics(pcVPS->getNumReorderPics(0), i); pcVPS->setMaxLatencyIncrease(pcVPS->getMaxLatencyIncrease(0), i); } break; } } assert( pcVPS->getNumHrdParameters() < MAX_VPS_OP_SETS_PLUS1 ); assert( pcVPS->getMaxNuhReservedZeroLayerId() < MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 ); READ_CODE( 6, uiCode, "vps_max_layer_id" ); pcVPS->setMaxNuhReservedZeroLayerId( uiCode ); READ_UVLC( uiCode, "vps_num_layer_sets_minus1" ); pcVPS->setMaxOpSets( uiCode + 1 ); for( UInt opsIdx = 1; opsIdx <= ( pcVPS->getMaxOpSets() - 1 ); opsIdx ++ ) { // Operation point set for( UInt i = 0; i <= pcVPS->getMaxNuhReservedZeroLayerId(); i ++ ) { READ_FLAG( uiCode, "layer_id_included_flag[opsIdx][i]" ); pcVPS->setLayerIdIncludedFlag( uiCode == 1 ? true : false, opsIdx, i ); } } TimingInfo *timingInfo = pcVPS->getTimingInfo(); READ_FLAG( uiCode, "vps_timing_info_present_flag"); timingInfo->setTimingInfoPresentFlag (uiCode ? true : false); if(timingInfo->getTimingInfoPresentFlag()) { READ_CODE( 32, uiCode, "vps_num_units_in_tick"); timingInfo->setNumUnitsInTick (uiCode); READ_CODE( 32, uiCode, "vps_time_scale"); timingInfo->setTimeScale (uiCode); READ_FLAG( uiCode, "vps_poc_proportional_to_timing_flag"); timingInfo->setPocProportionalToTimingFlag(uiCode ? true : false); if(timingInfo->getPocProportionalToTimingFlag()) { READ_UVLC( uiCode, "vps_num_ticks_poc_diff_one_minus1"); timingInfo->setNumTicksPocDiffOneMinus1 (uiCode); } READ_UVLC( uiCode, "vps_num_hrd_parameters" ); pcVPS->setNumHrdParameters( uiCode ); if( pcVPS->getNumHrdParameters() > 0 ) { pcVPS->createHrdParamBuffer(); } for( UInt i = 0; i < pcVPS->getNumHrdParameters(); i ++ ) { READ_UVLC( uiCode, "hrd_layer_set_idx[i]" ); pcVPS->setHrdOpSetIdx( uiCode, i ); if( i > 0 ) { READ_FLAG( uiCode, "cprms_present_flag[i]" ); pcVPS->setCprmsPresentFlag( uiCode == 1 ? true : false, i ); } else { pcVPS->setCprmsPresentFlag( true, i ); } parseHrdParameters(pcVPS->getHrdParameters(i), pcVPS->getCprmsPresentFlag( i ), pcVPS->getMaxTLayers() - 1); } } READ_FLAG( uiCode, "vps_extension_flag" ); if (uiCode) { while ( xMoreRbspData() ) { READ_FLAG( uiCode, "vps_extension_data_flag"); } } xReadRbspTrailingBits(); } Void TDecCavlc::parseSliceHeader (TComSlice* pcSlice, ParameterSetManager *parameterSetManager, const Int prevTid0POC) { UInt uiCode; Int iCode; #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceSliceHeaderDec(); #else xTraceSliceHeader(); #endif #endif TComPPS* pps = NULL; TComSPS* sps = NULL; UInt firstSliceSegmentInPic; READ_FLAG( firstSliceSegmentInPic, "first_slice_segment_in_pic_flag" ); if( pcSlice->getRapPicFlag()) { READ_FLAG( uiCode, "no_output_of_prior_pics_flag" ); //ignored -- updated already pcSlice->setNoOutputPriorPicsFlag(uiCode ? true : false); } READ_UVLC ( uiCode, "slice_pic_parameter_set_id" ); pcSlice->setPPSId(uiCode); pps = parameterSetManager->getPPS(uiCode); //!KS: need to add error handling code here, if PPS is not available assert(pps!=0); sps = parameterSetManager->getSPS(pps->getSPSId()); //!KS: need to add error handling code here, if SPS is not available assert(sps!=0); const ChromaFormat chFmt = sps->getChromaFormatIdc(); const UInt numValidComp=getNumberValidComponents(chFmt); const Bool bChroma=(chFmt!=CHROMA_400); if( pps->getDependentSliceSegmentsEnabledFlag() && ( !firstSliceSegmentInPic )) { READ_FLAG( uiCode, "dependent_slice_segment_flag" ); pcSlice->setDependentSliceSegmentFlag(uiCode ? true : false); } else { pcSlice->setDependentSliceSegmentFlag(false); } Int numCTUs = ((sps->getPicWidthInLumaSamples()+sps->getMaxCUWidth()-1)/sps->getMaxCUWidth())*((sps->getPicHeightInLumaSamples()+sps->getMaxCUHeight()-1)/sps->getMaxCUHeight()); UInt sliceSegmentAddress = 0; Int bitsSliceSegmentAddress = 0; while(numCTUs>(1<setSliceSegmentCurStartCtuTsAddr( sliceSegmentAddress );// this is actually a Raster-Scan (RS) address, but we do not have the RS->TS conversion table defined yet. pcSlice->setSliceSegmentCurEndCtuTsAddr(numCTUs); // Set end as the last CTU of the picture. if (!pcSlice->getDependentSliceSegmentFlag()) { pcSlice->setSliceCurStartCtuTsAddr(sliceSegmentAddress); // this is actually a Raster-Scan (RS) address, but we do not have the RS->TS conversion table defined yet. pcSlice->setSliceCurEndCtuTsAddr(numCTUs); } if(!pcSlice->getDependentSliceSegmentFlag()) { for (Int i = 0; i < pps->getNumExtraSliceHeaderBits(); i++) { READ_FLAG(uiCode, "slice_reserved_flag[]"); // ignored } READ_UVLC ( uiCode, "slice_type" ); pcSlice->setSliceType((SliceType)uiCode); if( pps->getOutputFlagPresentFlag() ) { READ_FLAG( uiCode, "pic_output_flag" ); pcSlice->setPicOutputFlag( uiCode ? true : false ); } else { pcSlice->setPicOutputFlag( true ); } // if (separate_colour_plane_flag == 1) // read colour_plane_id // (separate_colour_plane_flag == 1) is not supported in this version of the standard. if( pcSlice->getIdrPicFlag() ) { pcSlice->setPOC(0); TComReferencePictureSet* rps = pcSlice->getLocalRPS(); (*rps)=TComReferencePictureSet(); pcSlice->setRPS(rps); } else { READ_CODE(sps->getBitsForPOC(), uiCode, "slice_pic_order_cnt_lsb"); Int iPOClsb = uiCode; Int iPrevPOC = prevTid0POC; Int iMaxPOClsb = 1<< sps->getBitsForPOC(); Int iPrevPOClsb = iPrevPOC & (iMaxPOClsb - 1); Int iPrevPOCmsb = iPrevPOC-iPrevPOClsb; Int iPOCmsb; if( ( iPOClsb < iPrevPOClsb ) && ( ( iPrevPOClsb - iPOClsb ) >= ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb + iMaxPOClsb; } else if( (iPOClsb > iPrevPOClsb ) && ( (iPOClsb - iPrevPOClsb ) > ( iMaxPOClsb / 2 ) ) ) { iPOCmsb = iPrevPOCmsb - iMaxPOClsb; } else { iPOCmsb = iPrevPOCmsb; } if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) { // For BLA picture types, POCmsb is set to 0. iPOCmsb = 0; } pcSlice->setPOC (iPOCmsb+iPOClsb); TComReferencePictureSet* rps; rps = pcSlice->getLocalRPS(); (*rps)=TComReferencePictureSet(); pcSlice->setRPS(rps); READ_FLAG( uiCode, "short_term_ref_pic_set_sps_flag" ); if(uiCode == 0) // use short-term reference picture set explicitly signalled in slice header { parseShortTermRefPicSet(sps,rps, sps->getRPSList()->getNumberOfReferencePictureSets()); #if MCTS_EXTRACTION pcSlice->setRPSidx(-1); // when -1, reference picture set explicitly signalled in slice header, otherwise identify the PPS RPS; added for MCTS extraction #endif } else // use reference to short-term reference picture set in PPS { Int numBits = 0; while ((1 << numBits) < sps->getRPSList()->getNumberOfReferencePictureSets()) { numBits++; } if (numBits > 0) { READ_CODE( numBits, uiCode, "short_term_ref_pic_set_idx"); #if MCTS_EXTRACTION pcSlice->setRPSidx(uiCode); // when -1, reference picture set explicitly signalled in slice header, otherwise identify the PPS RPS; added for MCTS extraction #endif } else { uiCode = 0; } *rps = *(sps->getRPSList()->getReferencePictureSet(uiCode)); } if(sps->getLongTermRefsPresent()) { Int offset = rps->getNumberOfNegativePictures()+rps->getNumberOfPositivePictures(); UInt numOfLtrp = 0; UInt numLtrpInSPS = 0; if (sps->getNumLongTermRefPicSPS() > 0) { READ_UVLC( uiCode, "num_long_term_sps"); numLtrpInSPS = uiCode; numOfLtrp += numLtrpInSPS; rps->setNumberOfLongtermPictures(numOfLtrp); } Int bitsForLtrpInSPS = 0; while (sps->getNumLongTermRefPicSPS() > (1 << bitsForLtrpInSPS)) { bitsForLtrpInSPS++; } READ_UVLC( uiCode, "num_long_term_pics"); rps->setNumberOfLongtermPictures(uiCode); numOfLtrp += uiCode; rps->setNumberOfLongtermPictures(numOfLtrp); Int maxPicOrderCntLSB = 1 << sps->getBitsForPOC(); Int prevDeltaMSB = 0, deltaPocMSBCycleLT = 0; for(Int j=offset+rps->getNumberOfLongtermPictures()-1, k = 0; k < numOfLtrp; j--, k++) { Int pocLsbLt; if (k < numLtrpInSPS) { uiCode = 0; if (bitsForLtrpInSPS > 0) { READ_CODE(bitsForLtrpInSPS, uiCode, "lt_idx_sps[i]"); } Bool usedByCurrFromSPS=sps->getUsedByCurrPicLtSPSFlag(uiCode); pocLsbLt = sps->getLtRefPicPocLsbSps(uiCode); rps->setUsed(j,usedByCurrFromSPS); } else { READ_CODE(sps->getBitsForPOC(), uiCode, "poc_lsb_lt"); pocLsbLt= uiCode; READ_FLAG( uiCode, "used_by_curr_pic_lt_flag"); rps->setUsed(j,uiCode); } READ_FLAG(uiCode,"delta_poc_msb_present_flag"); Bool mSBPresentFlag = uiCode ? true : false; if(mSBPresentFlag) { READ_UVLC( uiCode, "delta_poc_msb_cycle_lt[i]" ); Bool deltaFlag = false; // First LTRP || First LTRP from SH if( (j == offset+rps->getNumberOfLongtermPictures()-1) || (j == offset+(numOfLtrp-numLtrpInSPS)-1) ) { deltaFlag = true; } if(deltaFlag) { deltaPocMSBCycleLT = uiCode; } else { deltaPocMSBCycleLT = uiCode + prevDeltaMSB; } Int pocLTCurr = pcSlice->getPOC() - deltaPocMSBCycleLT * maxPicOrderCntLSB - iPOClsb + pocLsbLt; rps->setPOC (j, pocLTCurr); rps->setDeltaPOC(j, - pcSlice->getPOC() + pocLTCurr); rps->setCheckLTMSBPresent(j,true); } else { rps->setPOC (j, pocLsbLt); rps->setDeltaPOC(j, - pcSlice->getPOC() + pocLsbLt); rps->setCheckLTMSBPresent(j,false); // reset deltaPocMSBCycleLT for first LTRP from slice header if MSB not present if( j == offset+(numOfLtrp-numLtrpInSPS)-1 ) { deltaPocMSBCycleLT = 0; } } prevDeltaMSB = deltaPocMSBCycleLT; } offset += rps->getNumberOfLongtermPictures(); rps->setNumberOfPictures(offset); } if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) { // In the case of BLA picture types, rps data is read from slice header but ignored rps = pcSlice->getLocalRPS(); (*rps)=TComReferencePictureSet(); pcSlice->setRPS(rps); } if (sps->getSPSTemporalMVPEnabledFlag()) { READ_FLAG( uiCode, "slice_temporal_mvp_enabled_flag" ); pcSlice->setEnableTMVPFlag( uiCode == 1 ? true : false ); } else { pcSlice->setEnableTMVPFlag(false); } } if(sps->getUseSAO()) { READ_FLAG(uiCode, "slice_sao_luma_flag"); pcSlice->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, (Bool)uiCode); if (bChroma) { READ_FLAG(uiCode, "slice_sao_chroma_flag"); pcSlice->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, (Bool)uiCode); } } if (pcSlice->getIdrPicFlag()) { pcSlice->setEnableTMVPFlag(false); } if (!pcSlice->isIntra()) { READ_FLAG( uiCode, "num_ref_idx_active_override_flag"); if (uiCode) { READ_UVLC (uiCode, "num_ref_idx_l0_active_minus1" ); pcSlice->setNumRefIdx( REF_PIC_LIST_0, uiCode + 1 ); if (pcSlice->isInterB()) { READ_UVLC (uiCode, "num_ref_idx_l1_active_minus1" ); pcSlice->setNumRefIdx( REF_PIC_LIST_1, uiCode + 1 ); } else { pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); } } else { pcSlice->setNumRefIdx(REF_PIC_LIST_0, pps->getNumRefIdxL0DefaultActive()); if (pcSlice->isInterB()) { pcSlice->setNumRefIdx(REF_PIC_LIST_1, pps->getNumRefIdxL1DefaultActive()); } else { pcSlice->setNumRefIdx(REF_PIC_LIST_1,0); } } } // } TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification(); if(!pcSlice->isIntra()) { if( !pps->getListsModificationPresentFlag() || pcSlice->getNumRpsCurrTempList() <= 1 ) { refPicListModification->setRefPicListModificationFlagL0( 0 ); } else { READ_FLAG( uiCode, "ref_pic_list_modification_flag_l0" ); refPicListModification->setRefPicListModificationFlagL0( uiCode ? 1 : 0 ); } if(refPicListModification->getRefPicListModificationFlagL0()) { uiCode = 0; Int i = 0; Int numRpsCurrTempList0 = pcSlice->getNumRpsCurrTempList(); if ( numRpsCurrTempList0 > 1 ) { Int length = 1; numRpsCurrTempList0 --; while ( numRpsCurrTempList0 >>= 1) { length ++; } for (i = 0; i < pcSlice->getNumRefIdx(REF_PIC_LIST_0); i ++) { READ_CODE( length, uiCode, "list_entry_l0" ); refPicListModification->setRefPicSetIdxL0(i, uiCode ); } } else { for (i = 0; i < pcSlice->getNumRefIdx(REF_PIC_LIST_0); i ++) { refPicListModification->setRefPicSetIdxL0(i, 0 ); } } } } else { refPicListModification->setRefPicListModificationFlagL0(0); } if(pcSlice->isInterB()) { if( !pps->getListsModificationPresentFlag() || pcSlice->getNumRpsCurrTempList() <= 1 ) { refPicListModification->setRefPicListModificationFlagL1( 0 ); } else { READ_FLAG( uiCode, "ref_pic_list_modification_flag_l1" ); refPicListModification->setRefPicListModificationFlagL1( uiCode ? 1 : 0 ); } if(refPicListModification->getRefPicListModificationFlagL1()) { uiCode = 0; Int i = 0; Int numRpsCurrTempList1 = pcSlice->getNumRpsCurrTempList(); if ( numRpsCurrTempList1 > 1 ) { Int length = 1; numRpsCurrTempList1 --; while ( numRpsCurrTempList1 >>= 1) { length ++; } for (i = 0; i < pcSlice->getNumRefIdx(REF_PIC_LIST_1); i ++) { READ_CODE( length, uiCode, "list_entry_l1" ); refPicListModification->setRefPicSetIdxL1(i, uiCode ); } } else { for (i = 0; i < pcSlice->getNumRefIdx(REF_PIC_LIST_1); i ++) { refPicListModification->setRefPicSetIdxL1(i, 0 ); } } } } else { refPicListModification->setRefPicListModificationFlagL1(0); } if (pcSlice->isInterB()) { READ_FLAG( uiCode, "mvd_l1_zero_flag" ); pcSlice->setMvdL1ZeroFlag( (uiCode ? true : false) ); } pcSlice->setCabacInitFlag( false ); // default if(pps->getCabacInitPresentFlag() && !pcSlice->isIntra()) { READ_FLAG(uiCode, "cabac_init_flag"); pcSlice->setCabacInitFlag( uiCode ? true : false ); } if ( pcSlice->getEnableTMVPFlag() ) { if ( pcSlice->getSliceType() == B_SLICE ) { READ_FLAG( uiCode, "collocated_from_l0_flag" ); pcSlice->setColFromL0Flag(uiCode); } else { pcSlice->setColFromL0Flag( 1 ); } if ( pcSlice->getSliceType() != I_SLICE && ((pcSlice->getColFromL0Flag() == 1 && pcSlice->getNumRefIdx(REF_PIC_LIST_0) > 1)|| (pcSlice->getColFromL0Flag() == 0 && pcSlice->getNumRefIdx(REF_PIC_LIST_1) > 1))) { READ_UVLC( uiCode, "collocated_ref_idx" ); pcSlice->setColRefIdx(uiCode); } else { pcSlice->setColRefIdx(0); } } if ( (pps->getUseWP() && pcSlice->getSliceType()==P_SLICE) || (pps->getWPBiPred() && pcSlice->getSliceType()==B_SLICE) ) { xParsePredWeightTable(pcSlice, sps); pcSlice->initWpScaling(sps); } if (!pcSlice->isIntra()) { READ_UVLC( uiCode, "five_minus_max_num_merge_cand"); pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); } READ_SVLC( iCode, "slice_qp_delta" ); pcSlice->setSliceQp (26 + pps->getPicInitQPMinus26() + iCode); assert( pcSlice->getSliceQp() >= -sps->getQpBDOffset(CHANNEL_TYPE_LUMA) ); assert( pcSlice->getSliceQp() <= 51 ); if (pps->getSliceChromaQpFlag()) { if (numValidComp>COMPONENT_Cb) { READ_SVLC( iCode, "slice_cb_qp_offset" ); pcSlice->setSliceChromaQpDelta(COMPONENT_Cb, iCode ); assert( pcSlice->getSliceChromaQpDelta(COMPONENT_Cb) >= -12 ); assert( pcSlice->getSliceChromaQpDelta(COMPONENT_Cb) <= 12 ); assert( (pps->getQpOffset(COMPONENT_Cb) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cb)) >= -12 ); assert( (pps->getQpOffset(COMPONENT_Cb) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cb)) <= 12 ); } if (numValidComp>COMPONENT_Cr) { READ_SVLC( iCode, "slice_cr_qp_offset" ); pcSlice->setSliceChromaQpDelta(COMPONENT_Cr, iCode ); assert( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr) >= -12 ); assert( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr) <= 12 ); assert( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) >= -12 ); assert( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) <= 12 ); } } if (pps->getPpsRangeExtension().getChromaQpOffsetListEnabledFlag()) { READ_FLAG(uiCode, "cu_chroma_qp_offset_enabled_flag"); pcSlice->setUseChromaQpAdj(uiCode != 0); } else { pcSlice->setUseChromaQpAdj(false); } if (pps->getDeblockingFilterControlPresentFlag()) { if(pps->getDeblockingFilterOverrideEnabledFlag()) { READ_FLAG ( uiCode, "deblocking_filter_override_flag" ); pcSlice->setDeblockingFilterOverrideFlag(uiCode ? true : false); } else { pcSlice->setDeblockingFilterOverrideFlag(0); } if(pcSlice->getDeblockingFilterOverrideFlag()) { READ_FLAG ( uiCode, "slice_deblocking_filter_disabled_flag" ); pcSlice->setDeblockingFilterDisable(uiCode ? 1 : 0); if(!pcSlice->getDeblockingFilterDisable()) { READ_SVLC( iCode, "slice_beta_offset_div2" ); pcSlice->setDeblockingFilterBetaOffsetDiv2(iCode); assert(pcSlice->getDeblockingFilterBetaOffsetDiv2() >= -6 && pcSlice->getDeblockingFilterBetaOffsetDiv2() <= 6); READ_SVLC( iCode, "slice_tc_offset_div2" ); pcSlice->setDeblockingFilterTcOffsetDiv2(iCode); assert(pcSlice->getDeblockingFilterTcOffsetDiv2() >= -6 && pcSlice->getDeblockingFilterTcOffsetDiv2() <= 6); } } else { pcSlice->setDeblockingFilterDisable ( pps->getPPSDeblockingFilterDisabledFlag() ); pcSlice->setDeblockingFilterBetaOffsetDiv2( pps->getDeblockingFilterBetaOffsetDiv2() ); pcSlice->setDeblockingFilterTcOffsetDiv2 ( pps->getDeblockingFilterTcOffsetDiv2() ); } } else { pcSlice->setDeblockingFilterDisable ( false ); pcSlice->setDeblockingFilterBetaOffsetDiv2( 0 ); pcSlice->setDeblockingFilterTcOffsetDiv2 ( 0 ); } Bool isSAOEnabled = sps->getUseSAO() && (pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA) || (bChroma && pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA))); Bool isDBFEnabled = (!pcSlice->getDeblockingFilterDisable()); if(pps->getLoopFilterAcrossSlicesEnabledFlag() && ( isSAOEnabled || isDBFEnabled )) { READ_FLAG( uiCode, "slice_loop_filter_across_slices_enabled_flag"); } else { uiCode = pps->getLoopFilterAcrossSlicesEnabledFlag()?1:0; } pcSlice->setLFCrossSliceBoundaryFlag( (uiCode==1)?true:false); } std::vector entryPointOffset; if( pps->getTilesEnabledFlag() || pps->getEntropyCodingSyncEnabledFlag() ) { UInt numEntryPointOffsets; UInt offsetLenMinus1; READ_UVLC(numEntryPointOffsets, "num_entry_point_offsets"); if (numEntryPointOffsets>0) { READ_UVLC(offsetLenMinus1, "offset_len_minus1"); entryPointOffset.resize(numEntryPointOffsets); for (UInt idx=0; idxgetSliceHeaderExtensionPresentFlag()) { READ_UVLC(uiCode,"slice_segment_header_extension_length"); for(Int i=0; ireadByteAlignment(),0); #else m_pcBitstream->readByteAlignment(); #endif pcSlice->clearSubstreamSizes(); if( pps->getTilesEnabledFlag() || pps->getEntropyCodingSyncEnabledFlag() ) { Int endOfSliceHeaderLocation = m_pcBitstream->getByteLocation(); // Adjust endOfSliceHeaderLocation to account for emulation prevention bytes in the slice segment header for ( UInt curByteIdx = 0; curByteIdxnumEmulationPreventionBytesRead(); curByteIdx++ ) { if ( m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) < endOfSliceHeaderLocation ) { endOfSliceHeaderLocation++; } } Int curEntryPointOffset = 0; Int prevEntryPointOffset = 0; for (UInt idx=0; idxnumEmulationPreventionBytesRead(); curByteIdx++ ) { if ( m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) >= ( prevEntryPointOffset + endOfSliceHeaderLocation ) && m_pcBitstream->getEmulationPreventionByteLocation( curByteIdx ) < ( curEntryPointOffset + endOfSliceHeaderLocation ) ) { emulationPreventionByteCount++; } } entryPointOffset[ idx ] -= emulationPreventionByteCount; prevEntryPointOffset = curEntryPointOffset; pcSlice->addSubstreamSize(entryPointOffset [ idx ] ); } } return; } Void TDecCavlc::parsePTL( TComPTL *rpcPTL, Bool profilePresentFlag, Int maxNumSubLayersMinus1 ) { UInt uiCode; if(profilePresentFlag) { parseProfileTier(rpcPTL->getGeneralPTL(), false); } READ_CODE( 8, uiCode, "general_level_idc" ); rpcPTL->getGeneralPTL()->setLevelIdc(Level::Name(uiCode)); for (Int i = 0; i < maxNumSubLayersMinus1; i++) { READ_FLAG( uiCode, "sub_layer_profile_present_flag[i]" ); rpcPTL->setSubLayerProfilePresentFlag(i, uiCode); READ_FLAG( uiCode, "sub_layer_level_present_flag[i]" ); rpcPTL->setSubLayerLevelPresentFlag (i, uiCode); } if (maxNumSubLayersMinus1 > 0) { for (Int i = maxNumSubLayersMinus1; i < 8; i++) { READ_CODE(2, uiCode, "reserved_zero_2bits"); assert(uiCode == 0); } } for(Int i = 0; i < maxNumSubLayersMinus1; i++) { if( rpcPTL->getSubLayerProfilePresentFlag(i) ) { parseProfileTier(rpcPTL->getSubLayerPTL(i), true); } if(rpcPTL->getSubLayerLevelPresentFlag(i)) { READ_CODE( 8, uiCode, "sub_layer_level_idc[i]" ); rpcPTL->getSubLayerPTL(i)->setLevelIdc(Level::Name(uiCode)); } } } #if ENC_DEC_TRACE || RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecCavlc::parseProfileTier(ProfileTierLevel *ptl, const Bool bIsSubLayer) #define PTL_TRACE_TEXT(txt) bIsSubLayer?("sub_layer_" txt) : ("general_" txt) #else Void TDecCavlc::parseProfileTier(ProfileTierLevel *ptl, const Bool /*bIsSubLayer*/) #define PTL_TRACE_TEXT(txt) txt #endif { UInt uiCode; READ_CODE(2 , uiCode, PTL_TRACE_TEXT("profile_space" )); ptl->setProfileSpace(uiCode); READ_FLAG( uiCode, PTL_TRACE_TEXT("tier_flag" )); ptl->setTierFlag (uiCode ? Level::HIGH : Level::MAIN); READ_CODE(5 , uiCode, PTL_TRACE_TEXT("profile_idc" )); ptl->setProfileIdc (Profile::Name(uiCode)); for(Int j = 0; j < 32; j++) { READ_FLAG( uiCode, PTL_TRACE_TEXT("profile_compatibility_flag[][j]" )); ptl->setProfileCompatibilityFlag(j, uiCode ? 1 : 0); } READ_FLAG(uiCode, PTL_TRACE_TEXT("progressive_source_flag" )); ptl->setProgressiveSourceFlag(uiCode ? true : false); READ_FLAG(uiCode, PTL_TRACE_TEXT("interlaced_source_flag" )); ptl->setInterlacedSourceFlag(uiCode ? true : false); READ_FLAG(uiCode, PTL_TRACE_TEXT("non_packed_constraint_flag" )); ptl->setNonPackedConstraintFlag(uiCode ? true : false); READ_FLAG(uiCode, PTL_TRACE_TEXT("frame_only_constraint_flag" )); ptl->setFrameOnlyConstraintFlag(uiCode ? true : false); if (ptl->getProfileIdc() == Profile::MAINREXT || ptl->getProfileCompatibilityFlag(Profile::MAINREXT) || ptl->getProfileIdc() == Profile::HIGHTHROUGHPUTREXT || ptl->getProfileCompatibilityFlag(Profile::HIGHTHROUGHPUTREXT)) { UInt maxBitDepth=16; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_12bit_constraint_flag" )); if (uiCode) maxBitDepth=12; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_10bit_constraint_flag" )); if (uiCode) maxBitDepth=10; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_8bit_constraint_flag" )); if (uiCode) maxBitDepth=8; ptl->setBitDepthConstraint(maxBitDepth); ChromaFormat chromaFmtConstraint=CHROMA_444; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_422chroma_constraint_flag" )); if (uiCode) chromaFmtConstraint=CHROMA_422; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_420chroma_constraint_flag" )); if (uiCode) chromaFmtConstraint=CHROMA_420; READ_FLAG( uiCode, PTL_TRACE_TEXT("max_monochrome_constraint_flag" )); if (uiCode) chromaFmtConstraint=CHROMA_400; ptl->setChromaFormatConstraint(chromaFmtConstraint); READ_FLAG( uiCode, PTL_TRACE_TEXT("intra_constraint_flag" )); ptl->setIntraConstraintFlag(uiCode != 0); READ_FLAG( uiCode, PTL_TRACE_TEXT("one_picture_only_constraint_flag")); ptl->setOnePictureOnlyConstraintFlag(uiCode != 0); READ_FLAG( uiCode, PTL_TRACE_TEXT("lower_bit_rate_constraint_flag" )); ptl->setLowerBitRateConstraintFlag(uiCode != 0); READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_34bits[0..15]" )); READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_34bits[16..31]" )); READ_CODE(2, uiCode, PTL_TRACE_TEXT("reserved_zero_34bits[32..33]" )); } else { ptl->setBitDepthConstraint((ptl->getProfileIdc() == Profile::MAIN10)?10:8); ptl->setChromaFormatConstraint(CHROMA_420); ptl->setIntraConstraintFlag(false); ptl->setLowerBitRateConstraintFlag(true); if (ptl->getProfileIdc() == Profile::MAIN10 || ptl->getProfileCompatibilityFlag(Profile::MAIN10)) { READ_CODE(7, uiCode, PTL_TRACE_TEXT("reserved_zero_7bits" )); READ_FLAG( uiCode, PTL_TRACE_TEXT("one_picture_only_constraint_flag")); ptl->setOnePictureOnlyConstraintFlag(uiCode != 0); READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_35bits[0..15]" )); READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_35bits[16..31]" )); READ_CODE(3, uiCode, PTL_TRACE_TEXT("reserved_zero_35bits[32..34]" )); } else { READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_43bits[0..15]" )); READ_CODE(16, uiCode, PTL_TRACE_TEXT("reserved_zero_43bits[16..31]" )); READ_CODE(11, uiCode, PTL_TRACE_TEXT("reserved_zero_43bits[32..42]" )); } } if ((ptl->getProfileIdc() >= Profile::MAIN && ptl->getProfileIdc() <= Profile::HIGHTHROUGHPUTREXT) || ptl->getProfileCompatibilityFlag(Profile::MAIN) || ptl->getProfileCompatibilityFlag(Profile::MAIN10) || ptl->getProfileCompatibilityFlag(Profile::MAINSTILLPICTURE) || ptl->getProfileCompatibilityFlag(Profile::MAINREXT) || ptl->getProfileCompatibilityFlag(Profile::HIGHTHROUGHPUTREXT) ) { READ_FLAG( uiCode, PTL_TRACE_TEXT("inbld_flag" )); assert(uiCode == 0); } else { READ_FLAG( uiCode, PTL_TRACE_TEXT("reserved_zero_bit" )); } #undef PTL_TRACE_TEXT } Void TDecCavlc::parseTerminatingBit( UInt& ruiBit ) { ruiBit = false; Int iBitsLeft = m_pcBitstream->getNumBitsLeft(); if(iBitsLeft <= 8) { UInt uiPeekValue = m_pcBitstream->peekBits(iBitsLeft); if (uiPeekValue == (1<<(iBitsLeft-1))) { ruiBit = true; } } } Void TDecCavlc::parseRemainingBytes( Bool noTrailingBytesExpected ) { if (noTrailingBytesExpected) { const UInt numberOfRemainingSubstreamBytes=m_pcBitstream->getNumBitsLeft(); assert (numberOfRemainingSubstreamBytes == 0); } else { while (m_pcBitstream->getNumBitsLeft()) { UInt trailingNullByte=m_pcBitstream->readByte(); if (trailingNullByte!=0) { printf("Trailing byte should be 0, but has value %02x\n", trailingNullByte); assert(trailingNullByte==0); } } } } Void TDecCavlc::parseSkipFlag( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseCUTransquantBypassFlag( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseMVPIdx( Int& /*riMVPIdx*/ ) { assert(0); } Void TDecCavlc::parseSplitFlag ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parsePartSize( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parsePredMode( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } /** Parse I_PCM information. * \param pcCU pointer to CU * \param uiAbsPartIdx CU index * \param uiDepth CU depth * \returns Void * * If I_PCM flag indicates that the CU is I_PCM, parse its PCM alignment bits and codes. */ Void TDecCavlc::parseIPCMInfo( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseIntraDirLumaAng ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseIntraDirChroma( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseInterDir( TComDataCU* /*pcCU*/, UInt& /*ruiInterDir*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TDecCavlc::parseRefFrmIdx( TComDataCU* /*pcCU*/, Int& /*riRefFrmIdx*/, RefPicList /*eRefList*/ ) { assert(0); } Void TDecCavlc::parseMvd( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiPartIdx*/, UInt /*uiDepth*/, RefPicList /*eRefList*/ ) { assert(0); } Void TDecCavlc::parseCrossComponentPrediction( class TComTU& /*rTu*/, ComponentID /*compID*/ ) { assert(0); } Void TDecCavlc::parseDeltaQP( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseChromaQpAdjustment( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TDecCavlc::parseCoeffNxN( TComTU &/*rTu*/, ComponentID /*compID*/ ) { assert(0); } Void TDecCavlc::parseTransformSubdivFlag( UInt& /*ruiSubdivFlag*/, UInt /*uiLog2TransformBlockSize*/ ) { assert(0); } Void TDecCavlc::parseQtCbf( TComTU &/*rTu*/, const ComponentID /*compID*/, const Bool /*lowestLevel*/ ) { assert(0); } Void TDecCavlc::parseQtRootCbf( UInt /*uiAbsPartIdx*/, UInt& /*uiQtRootCbf*/ ) { assert(0); } Void TDecCavlc::parseTransformSkipFlags (TComTU &/*rTu*/, ComponentID /*component*/) { assert(0); } Void TDecCavlc::parseMergeFlag ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/, UInt /*uiPUIdx*/ ) { assert(0); } Void TDecCavlc::parseMergeIndex ( TComDataCU* /*pcCU*/, UInt& /*ruiMergeIndex*/ ) { assert(0); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== //! parse explicit wp tables Void TDecCavlc::xParsePredWeightTable( TComSlice* pcSlice, const TComSPS *sps ) { WPScalingParam *wp; const ChromaFormat chFmt = sps->getChromaFormatIdc(); const Int numValidComp = Int(getNumberValidComponents(chFmt)); const Bool bChroma = (chFmt!=CHROMA_400); const SliceType eSliceType = pcSlice->getSliceType(); const Int iNbRef = (eSliceType == B_SLICE ) ? (2) : (1); UInt uiLog2WeightDenomLuma=0, uiLog2WeightDenomChroma=0; UInt uiTotalSignalledWeightFlags = 0; Int iDeltaDenom; // decode delta_luma_log2_weight_denom : READ_UVLC( uiLog2WeightDenomLuma, "luma_log2_weight_denom" ); assert( uiLog2WeightDenomLuma <= 7 ); if( bChroma ) { READ_SVLC( iDeltaDenom, "delta_chroma_log2_weight_denom" ); assert((iDeltaDenom + (Int)uiLog2WeightDenomLuma)>=0); assert((iDeltaDenom + (Int)uiLog2WeightDenomLuma)<=7); uiLog2WeightDenomChroma = (UInt)(iDeltaDenom + uiLog2WeightDenomLuma); } for ( Int iNumRef=0 ; iNumRefgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); wp[COMPONENT_Y].uiLog2WeightDenom = uiLog2WeightDenomLuma; for(Int j=1; jgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); READ_FLAG( uiCode, iNumRef==0?"chroma_weight_l0_flag[i]":"chroma_weight_l1_flag[i]" ); for(Int j=1; jgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); if ( wp[COMPONENT_Y].bPresentFlag ) { Int iDeltaWeight; READ_SVLC( iDeltaWeight, iNumRef==0?"delta_luma_weight_l0[i]":"delta_luma_weight_l1[i]" ); assert( iDeltaWeight >= -128 ); assert( iDeltaWeight <= 127 ); wp[COMPONENT_Y].iWeight = (iDeltaWeight + (1<getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? (1<getBitDepth(CHANNEL_TYPE_LUMA))/2 : 128; assert( wp[0].iOffset >= -range ); assert( wp[0].iOffset < range ); } else { wp[COMPONENT_Y].iWeight = (1 << wp[COMPONENT_Y].uiLog2WeightDenom); wp[COMPONENT_Y].iOffset = 0; } if ( bChroma ) { if ( wp[COMPONENT_Cb].bPresentFlag ) { Int range=sps->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? (1<getBitDepth(CHANNEL_TYPE_CHROMA))/2 : 128; for ( Int j=1 ; j= -128 ); assert( iDeltaWeight <= 127 ); wp[j].iWeight = (iDeltaWeight + (1<= -4*range); assert( iDeltaChroma < 4*range); Int pred = ( range - ( ( range*wp[j].iWeight)>>(wp[j].uiLog2WeightDenom) ) ); wp[j].iOffset = Clip3(-range, range-1, (iDeltaChroma + pred) ); } } else { for ( Int j=1 ; jgetNumRefIdx(eRefPicList) ; iRefIdxgetWpScaling(eRefPicList, iRefIdx, wp); wp[0].bPresentFlag = false; wp[1].bPresentFlag = false; wp[2].bPresentFlag = false; } } assert(uiTotalSignalledWeightFlags<=24); } /** decode quantization matrix * \param scalingList quantization matrix information */ Void TDecCavlc::parseScalingList(TComScalingList* scalingList) { UInt code, sizeId, listId; Bool scalingListPredModeFlag; //for each size for(sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { for(listId = 0; listId < SCALING_LIST_NUM; listId++) { if ((sizeId==SCALING_LIST_32x32) && (listId%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) != 0)) { Int *src = scalingList->getScalingListAddress(sizeId, listId); const Int size = min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId]); const Int *srcNextSmallerSize = scalingList->getScalingListAddress(sizeId-1, listId); for(Int i=0; isetScalingListDC(sizeId,listId,(sizeId > SCALING_LIST_8x8) ? scalingList->getScalingListDC(sizeId-1, listId) : src[0]); } else { READ_FLAG( code, "scaling_list_pred_mode_flag"); scalingListPredModeFlag = (code) ? true : false; scalingList->setScalingListPredModeFlag(sizeId, listId, scalingListPredModeFlag); if(!scalingListPredModeFlag) //Copy Mode { READ_UVLC( code, "scaling_list_pred_matrix_id_delta"); if (sizeId==SCALING_LIST_32x32) { code*=(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES); // Adjust the decoded code for this size, to cope with the missing 32x32 chroma entries. } scalingList->setRefMatrixId (sizeId,listId,(UInt)((Int)(listId)-(code))); if( sizeId > SCALING_LIST_8x8 ) { scalingList->setScalingListDC(sizeId,listId,((listId == scalingList->getRefMatrixId (sizeId,listId))? 16 :scalingList->getScalingListDC(sizeId, scalingList->getRefMatrixId (sizeId,listId)))); } scalingList->processRefMatrix( sizeId, listId, scalingList->getRefMatrixId (sizeId,listId)); } else //DPCM Mode { xDecodeScalingList(scalingList, sizeId, listId); } } } } return; } /** decode DPCM * \param scalingList quantization matrix information * \param sizeId size index * \param listId list index */ Void TDecCavlc::xDecodeScalingList(TComScalingList *scalingList, UInt sizeId, UInt listId) { Int i,coefNum = min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId]); Int data; Int scalingListDcCoefMinus8 = 0; Int nextCoef = SCALING_LIST_START_VALUE; UInt* scan = g_scanOrder[SCAN_UNGROUPED][SCAN_DIAG][sizeId==0 ? 2 : 3][sizeId==0 ? 2 : 3]; Int *dst = scalingList->getScalingListAddress(sizeId, listId); if( sizeId > SCALING_LIST_8x8 ) { READ_SVLC( scalingListDcCoefMinus8, "scaling_list_dc_coef_minus8"); scalingList->setScalingListDC(sizeId,listId,scalingListDcCoefMinus8 + 8); nextCoef = scalingList->getScalingListDC(sizeId,listId); } for(i = 0; i < coefNum; i++) { READ_SVLC( data, "scaling_list_delta_coef"); nextCoef = (nextCoef + data + 256 ) % 256; dst[scan[i]] = nextCoef; } } Bool TDecCavlc::xMoreRbspData() { Int bitsLeft = m_pcBitstream->getNumBitsLeft(); // if there are more than 8 bits, it cannot be rbsp_trailing_bits if (bitsLeft > 8) { return true; } UChar lastByte = m_pcBitstream->peekBits(bitsLeft); Int cnt = bitsLeft; // remove trailing bits equal to zero while ((cnt>0) && ((lastByte & 1) == 0)) { lastByte >>= 1; cnt--; } // remove bit equal to one cnt--; // we should not have a negative number of bits assert (cnt>=0); // we have more data, if cnt is not zero return (cnt>0); } Void TDecCavlc::parseExplicitRdpcmMode( TComTU& /*rTu*/, ComponentID /*compID*/ ) { assert(0); } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecCAVLC.h000066400000000000000000000133341442026013100201340ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecCAVLC.h \brief CAVLC decoder class (header) */ #ifndef __TDECCAVLC__ #define __TDECCAVLC__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TDecEntropy.h" #include "SyntaxElementParser.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// CAVLC decoder class class TDecCavlc : public SyntaxElementParser, public TDecEntropyIf { public: TDecCavlc(); virtual ~TDecCavlc(); protected: Void parseShortTermRefPicSet (TComSPS* pcSPS, TComReferencePictureSet* pcRPS, Int idx); public: /// rest entropy coder by intial QP and IDC in CABAC Void resetEntropy ( TComSlice* /*pcSlice*/ ) { assert(0); }; Void setBitstream ( TComInputBitstream* p ) { m_pcBitstream = p; } Void parseTransformSubdivFlag( UInt& ruiSubdivFlag, UInt uiLog2TransformBlockSize ); Void parseQtCbf ( class TComTU &rTu, const ComponentID compID, const Bool lowestLevel ); Void parseQtRootCbf ( UInt uiAbsPartIdx, UInt& uiQtRootCbf ); Void parseVPS ( TComVPS* pcVPS ); Void parseSPS ( TComSPS* pcSPS ); Void parsePPS ( TComPPS* pcPPS ); Void parseVUI ( TComVUI* pcVUI, TComSPS* pcSPS ); Void parseSEI ( SEIMessages& ); Void parsePTL ( TComPTL *rpcPTL, Bool profilePresentFlag, Int maxNumSubLayersMinus1 ); Void parseProfileTier (ProfileTierLevel *ptl, const Bool bIsSubLayer); Void parseHrdParameters (TComHRD *hrd, Bool cprms_present_flag, UInt tempLevelHigh); Void parseSliceHeader ( TComSlice* pcSlice, ParameterSetManager *parameterSetManager, const Int prevTid0POC); Void parseTerminatingBit ( UInt& ruiBit ); Void parseRemainingBytes ( Bool noTrailingBytesExpected ); Void parseMVPIdx ( Int& riMVPIdx ); Void parseSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ); Void parseMergeIndex ( TComDataCU* pcCU, UInt& ruiMergeIndex ); Void parseSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parsePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parsePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseIntraDirLumaAng ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseIntraDirChroma ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseInterDir ( TComDataCU* pcCU, UInt& ruiInterDir, UInt uiAbsPartIdx ); Void parseRefFrmIdx ( TComDataCU* pcCU, Int& riRefFrmIdx, RefPicList eRefList ); Void parseMvd ( TComDataCU* pcCU, UInt uiAbsPartAddr,UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ); Void parseCrossComponentPrediction( class TComTU &rTu, ComponentID compID ); Void parseDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseChromaQpAdjustment( TComDataCU* cu, UInt absPartIdx, UInt depth); Void parseCoeffNxN ( class TComTU &rTu, ComponentID compID ); Void parseTransformSkipFlags ( class TComTU &rTu, ComponentID component ); Void parseIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth); Void xParsePredWeightTable ( TComSlice* pcSlice, const TComSPS *sps ); Void parseScalingList ( TComScalingList* scalingList ); Void xDecodeScalingList ( TComScalingList *scalingList, UInt sizeId, UInt listId); Void parseExplicitRdpcmMode( TComTU &rTu, ComponentID compID ); protected: Bool xMoreRbspData(); }; //! \} #endif // !defined(AFX_TDECCAVLC_H__9732DD64_59B0_4A41_B29E_1A5B18821EAD__INCLUDED_) HM-HM-18.0/source/Lib/TLibDecoder/TDecConformance.cpp000066400000000000000000000646151442026013100221010ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecConformance.cpp \brief Decoder conformance functions */ #include "TDecConformance.h" #include "TLibCommon/TComSlice.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComPicSym.h" #include "NALread.h" #include #if !DPB_ENCODER_USAGE_CHECK UInt LevelTierFeatures::getMaxPicWidthInLumaSamples() const { return UInt(sqrt(maxLumaPs*8.0)); } UInt LevelTierFeatures::getMaxPicHeightInLumaSamples() const { return UInt(sqrt(maxLumaPs*8.0)); } #endif UInt TDecConformanceCheck::getMinLog2CtbSize(const TComPTL &ptl, UInt layerPlus1) { const ProfileTierLevel *pPTL = (layerPlus1==0) ? ptl.getGeneralPTL() : ptl.getSubLayerPTL(layerPlus1-1); return (pPTL->getLevelIdc() < Level::LEVEL5) ? 4 : 5; } UInt TDecConformanceCheck::getMaxLog2CtbSize(const TComPTL &/*ptl*/, UInt /*layerPlus1*/) { return MAX_CU_DEPTH; } TDecConformanceCheck::TDecConformanceCheck() #if MCTS_ENC_CHECK :m_tmctsCheckEnabled(false) #if DECODER_PARTIAL_CONFORMANCE_CHECK , m_numberOfSlicesInPicture(0) , m_bytesInPicture(0) #endif #else #if DECODER_PARTIAL_CONFORMANCE_CHECK : m_numberOfSlicesInPicture(0) , m_bytesInPicture(0) #endif #endif { } #if DECODER_PARTIAL_CONFORMANCE_CHECK != 0 #if !DPB_ENCODER_USAGE_CHECK static const UInt64 MAX_CNFUINT64 = std::numeric_limits::max(); static const LevelTierFeatures mainLevelTierInfo[] = { { Level::LEVEL1 , 36864, { 350, 0 }, 16, 1, 1, 552960ULL, { 128, 0 }, { 2, 2} }, { Level::LEVEL2 , 122880, { 1500, 0 }, 16, 1, 1, 3686400ULL, { 1500, 0 }, { 2, 2} }, { Level::LEVEL2_1, 245760, { 3000, 0 }, 20, 1, 1, 7372800ULL, { 3000, 0 }, { 2, 2} }, { Level::LEVEL3 , 552960, { 6000, 0 }, 30, 2, 2, 16588800ULL, { 6000, 0 }, { 2, 2} }, { Level::LEVEL3_1, 983040, { 10000, 0 }, 40, 3, 3, 33177600ULL, { 10000, 0 }, { 2, 2} }, { Level::LEVEL4 , 2228224, { 12000, 30000 }, 75, 5, 5, 66846720ULL, { 12000, 30000 }, { 4, 4} }, { Level::LEVEL4_1, 2228224, { 20000, 50000 }, 75, 5, 5, 133693440ULL, { 20000, 50000 }, { 4, 4} }, { Level::LEVEL5 , 8912896, { 25000, 100000 }, 200, 11, 10, 267386880ULL, { 25000, 100000 }, { 6, 4} }, { Level::LEVEL5_1, 8912896, { 40000, 160000 }, 200, 11, 10, 534773760ULL, { 40000, 160000 }, { 8, 4} }, { Level::LEVEL5_2, 8912896, { 60000, 240000 }, 200, 11, 10, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, { Level::LEVEL6 , 35651584, { 60000, 240000 }, 600, 22, 20, 1069547520ULL, { 60000, 240000 }, { 8, 4} }, { Level::LEVEL6_1, 35651584, { 120000, 480000 }, 600, 22, 20, 2139095040ULL, { 120000, 480000 }, { 8, 4} }, { Level::LEVEL6_2, 35651584, { 240000, 800000 }, 600, 22, 20, 4278190080ULL, { 240000, 800000 }, { 6, 4} }, { Level::LEVEL8_5, MAX_UINT, { MAX_UINT, MAX_UINT }, MAX_UINT, MAX_UINT, MAX_UINT, MAX_CNFUINT64, {MAX_UINT, MAX_UINT }, { 0, 0} }, { Level::NONE } }; static const ProfileFeatures validProfiles[] = { // profile, pNameString, maxBitDepth, maxChrFmt, intra, 1pic, lowerBR, RExtTools, ExtPrec , ChrmQPOf, align, HBRFactor, , wve+t, tiles,, lvl8.5, cpbvcl, cpbnal, fcf*1000, mincr*10 { Profile::MAIN, "Main", 8, CHROMA_420, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAIN10, "Main10", 10, CHROMA_420, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1 , false, 256, 64, false, 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAIN10, "Main10 Still Picture", 10, CHROMA_420, false, true, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1 , false, 256, 64, true , 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAINSTILLPICTURE, "Main Still Picture", 8, CHROMA_420, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1 , false, 256, 64, true , 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome", 8, CHROMA_400, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 667, 733, 1000, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome 12", 12, CHROMA_400, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Monochrome 16", 16, CHROMA_400, false, false, ENABLED , OPTIONAL, OPTIONAL, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1333, 1467, 2000, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 12", 12, CHROMA_420, false, false, ENABLED , DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1500, 1650, 2250, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 10", 10, CHROMA_422, false, false, ENABLED , DISABLED, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1667, 1833, 2500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 12", 12, CHROMA_422, false, false, ENABLED , DISABLED, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4", 8, CHROMA_444, false, false, ENABLED , OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 10", 10, CHROMA_444, false, false, ENABLED , OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2500, 2750, 3750, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 12", 12, CHROMA_444, false, false, ENABLED , OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 3000, 3300, 4500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main Intra", 8, CHROMA_420, true , false, OPTIONAL, DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1500, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 10 Intra", 10, CHROMA_420, true , false, OPTIONAL, DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1000, 1100, 1875, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 12 Intra", 12, CHROMA_420, true , false, OPTIONAL, DISABLED, DISABLED, DISABLED, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1500, 1650, 2250, 10 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 10 Intra", 10, CHROMA_422, true , false, OPTIONAL, DISABLED, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 1667, 1833, 2500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:2:2 12 Intra", 12, CHROMA_422, true , false, OPTIONAL, DISABLED, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 Intra", 8, CHROMA_444, true , false, OPTIONAL, OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 10 Intra", 10, CHROMA_444, true , false, OPTIONAL, OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 2500, 2750, 3750, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 12 Intra", 12, CHROMA_444, true , false, OPTIONAL, OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 3000, 3300, 4500, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 16 Intra", 16, CHROMA_444, true , false, OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, false, 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 Still Picture", 8, CHROMA_444, true , true , OPTIONAL, OPTIONAL, DISABLED, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, true , 2000, 2200, 3000, 5 , mainLevelTierInfo }, { Profile::MAINREXT, "Main 4:4:4 16 Still Picture", 16, CHROMA_444, true , true , OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, DISABLED, HBR_1_OR_2 , false, 256, 64, true , 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::HIGHTHROUGHPUTREXT, "High Throughput 4:4:4 16 Intra", 16, CHROMA_444, true , false, OPTIONAL, OPTIONAL, OPTIONAL, OPTIONAL, ENABLED , HBR_12_OR_24 , true , 256, 64, false, 4000, 4400, 6000, 5 , mainLevelTierInfo }, { Profile::NONE, 0 } }; #endif static Void checkSPS(const TComSPS &sps, const ProfileLevelTierFeatures &features) { // sps_max_sub_layers_minus1 shall be less than or equal to vsp_max_sub_layers_minus1 // TODO - check conformance of sps_max_dec_pic_buffering_minus1, sps_max_num_reorder_pics, sps_max_latency_increase_plus1 // needs VPS, which can only be done on activation. const UInt minCbSizeY = 1<<(sps.getLog2MinCodingBlockSize()); if (sps.getPicWidthInLumaSamples() % minCbSizeY != 0 ) { TDecConformanceCheck::getStream() << "picture width (" << sps.getPicWidthInLumaSamples() << ") must be a multiple of minCbSizeY (=" << minCbSizeY << ")\n"; TDecConformanceCheck::finishWarningReport(); } if (sps.getPicHeightInLumaSamples() % minCbSizeY != 0 ) { TDecConformanceCheck::getStream() << "picture height (" << sps.getPicHeightInLumaSamples() << ") must be a multiple of minCbSizeY (=" << minCbSizeY << ")\n"; TDecConformanceCheck::finishWarningReport(); } if (sps.getPicWidthInLumaSamples() > features.getLevelTierFeatures()->getMaxPicWidthInLumaSamples()) { TDecConformanceCheck::getStream() << "picture width (" << sps.getPicWidthInLumaSamples() << ") exceeds the maximum allowed by the level (" << features.getLevelTierFeatures()->getMaxPicWidthInLumaSamples() << ")\n"; TDecConformanceCheck::finishWarningReport(); } if (sps.getPicHeightInLumaSamples() > features.getLevelTierFeatures()->getMaxPicHeightInLumaSamples()) { TDecConformanceCheck::getStream() << "picture height (" << sps.getPicHeightInLumaSamples() << ") exceeds the maximum allowed by the level (" << features.getLevelTierFeatures()->getMaxPicHeightInLumaSamples() << ")\n"; TDecConformanceCheck::finishWarningReport(); } if (sps.getPicWidthInLumaSamples() * sps.getPicHeightInLumaSamples() > features.getLevelTierFeatures()->maxLumaPs) { TDecConformanceCheck::getStream() << "picture samples (" << sps.getPicWidthInLumaSamples() << " * " << sps.getPicHeightInLumaSamples() << ") exceeds the maximum allowed by the level (" << features.getLevelTierFeatures()->maxLumaPs << ")\n"; TDecConformanceCheck::finishWarningReport(); } } static Void checkTiles(const TComSPS &sps, const TComPPS &pps, const TComPic &pic, const ProfileLevelTierFeatures &features) { if (pps.getTilesEnabledFlag()) { // Tile size check const Int minWidthInCtus = features.getProfileFeatures()->minTileColumnWidthInLumaSamples/ sps.getMaxCUWidth(); const Int minHeightInCtus = features.getProfileFeatures()->minTileRowHeightInLumaSamples / sps.getMaxCUHeight(); const Int numCols = pps.getNumTileColumnsMinus1() + 1; const Int numRows = pps.getNumTileRowsMinus1() + 1; if (numCols > features.getLevelTierFeatures()->maxTileCols) { TDecConformanceCheck::getStream() << "number of tile columns (" << numCols << ") exceeds the maximum allowed by the level (" << features.getLevelTierFeatures()->maxTileCols << ")\n"; TDecConformanceCheck::finishWarningReport(); } if (numRows > features.getLevelTierFeatures()->maxTileRows) { TDecConformanceCheck::getStream() << "number of tile rows (" << numRows << ") exceeds the maximum allowed by the level (" << features.getLevelTierFeatures()->maxTileRows << ")\n"; TDecConformanceCheck::finishWarningReport(); } for(Int row=0; row < numRows; row++) { for(Int col=0; col < numCols; col++) { const Int tileIdx = row * numCols + col; const TComTile &tile = *(pic.getPicSym()->getTComTile(tileIdx)); if (tile.getTileWidthInCtus() < minWidthInCtus) { TDecConformanceCheck::getStream() << "width of tile (" << col << ", " << row << ") is too narrow for the profile - read " << tile.getTileWidthInCtus()*sps.getMaxCUWidth() << "must be " << minWidthInCtus*sps.getMaxCUWidth() << "\n"; TDecConformanceCheck::finishWarningReport(); } if (tile.getTileHeightInCtus() < minHeightInCtus) { TDecConformanceCheck::getStream() << "height of tile (" << col << ", " << row << ") is too thin for the profile - read " << tile.getTileHeightInCtus()*sps.getMaxCUHeight() << " must be " << minHeightInCtus*sps.getMaxCUHeight() << "\n"; TDecConformanceCheck::finishWarningReport(); } } } if (pps.getEntropyCodingSyncEnabledFlag() && !features.getProfileFeatures()->bWavefrontsAndTilesCanBeUsedSimultaneously) { TDecConformanceCheck::getStream() << "profile does not permit entropy coding sync and tiles to be simultaneously enabled\n"; TDecConformanceCheck::finishWarningReport(); } } } static Void checkPPS(const TComSPS &sps, const TComPPS &pps, const TComPic &pic, const ProfileLevelTierFeatures &features) { TDecConformanceCheck::checkRange(pps.getPicInitQPMinus26(), "init_qp_minus26", -(sps.getBitDepth(CHANNEL_TYPE_LUMA)-8)*6-26, 25); TDecConformanceCheck::checkRange(pps.getMaxCuDQPDepth(), "diff_cu_qp_delta_depth", 0, sps.getLog2DiffMaxMinCodingBlockSize()); TDecConformanceCheck::checkRange(pps.getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2", 0, sps.getLog2MinCodingBlockSize() + sps.getLog2DiffMaxMinCodingBlockSize() - 2); TDecConformanceCheck::checkRange(pps.getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_LUMA), "log2_sao_offset_scale_luma", 0, std::max(sps.getBitDepth(CHANNEL_TYPE_LUMA), 10)-10); TDecConformanceCheck::checkRange(pps.getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA), "log2_sao_offset_scale_chroma", 0, std::max(sps.getBitDepth(CHANNEL_TYPE_CHROMA), 10)-10); checkTiles(sps, pps, pic, features); } #if !DPB_ENCODER_USAGE_CHECK Void ProfileLevelTierFeatures::activate(const TComSPS &sps) { const ProfileTierLevel &ptl = *(sps.getPTL()->getGeneralPTL()); m_tier = ptl.getTierFlag(); for(Int i=0; validProfiles[i].profile != Profile::NONE; i++) { if (ptl.getProfileIdc() == validProfiles[i].profile && ptl.getBitDepthConstraint() == validProfiles[i].maxBitDepth && ptl.getChromaFormatConstraint() == validProfiles[i].maxChromaFormat && ptl.getIntraConstraintFlag() == validProfiles[i].generalIntraConstraintFlag && ptl.getOnePictureOnlyConstraintFlag() == validProfiles[i].generalOnePictureOnlyConstraintFlag ) { m_pProfile = &(validProfiles[i]); break; } } if (m_pProfile != 0) { // Now identify the level: const LevelTierFeatures *pLTF = m_pProfile->pLevelTiersListInfo; const Level::Name spsLevelName = sps.getPTL()->getGeneralPTL()->getLevelIdc(); if (spsLevelName!=Level::LEVEL8_5 || m_pProfile->bCanUseLevel8p5) { for(Int i=0; pLTF[i].level!=Level::NONE; i++) { if (pLTF[i].level == spsLevelName) { m_pLevelTier = &(pLTF[i]); } } } } { const UInt ctbSizeY = sps.getMaxCUWidth(); const UInt bitDepthY = sps.getBitDepth(CHANNEL_TYPE_LUMA); const UInt ctbWidthC = ctbSizeY >> getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, sps.getChromaFormatIdc()); const UInt ctbHeightC = ctbSizeY >> getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, sps.getChromaFormatIdc()); const UInt bitDepthC = sps.getBitDepth(CHANNEL_TYPE_LUMA); const UInt rawCtuBits = ctbSizeY*ctbSizeY*bitDepthY+2*(ctbWidthC*ctbHeightC)*bitDepthC; m_maxRawCtuBits=(rawCtuBits*5)/3; } } #endif static Void checkToolAvailability(const TComSPS &sps, const TComPPS &pps, const ProfileLevelTierFeatures &features) { #if DPB_ENCODER_USAGE_CHECK const ProfileFeatures::TRISTATE rextToolsEnabled = features.getProfileFeatures()->generalRExtToolsEnabled; if ( rextToolsEnabled != ProfileFeatures::OPTIONAL) { const Bool bWantedFlagState = rextToolsEnabled == ProfileFeatures::ENABLED; #else const TRISTATE rextToolsEnabled = features.getProfileFeatures()->generalRExtToolsEnabled; if ( rextToolsEnabled != OPTIONAL) { const Bool bWantedFlagState = rextToolsEnabled == ENABLED; #endif std::string flags; if (sps.getSpsRangeExtension().getTransformSkipRotationEnabledFlag() != bWantedFlagState) flags+=", transform_skip_rotation_enabled_flag"; if (sps.getSpsRangeExtension().getTransformSkipContextEnabledFlag() != bWantedFlagState) flags+=", transform_skip_context_enabled_flag"; if (sps.getSpsRangeExtension().getRdpcmEnabledFlag(RDPCM_SIGNAL_IMPLICIT) != bWantedFlagState) flags+=", implicit_rdpcm_enabled_flag"; if (sps.getSpsRangeExtension().getRdpcmEnabledFlag(RDPCM_SIGNAL_EXPLICIT) != bWantedFlagState) flags+=", explicit_rdpcm_enabled_flag"; if (sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag() != bWantedFlagState) flags+=", intra_smoothing_disabled_flag"; if (sps.getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag() != bWantedFlagState) flags+=", persistent_rice_adaptation_enabled_flag"; #if DPB_ENCODER_USAGE_CHECK if (pps.getPpsRangeExtension().getLog2MaxTransformSkipBlockSize() != 2 && rextToolsEnabled==ProfileFeatures::DISABLED ) flags+=", log2_max_transform_skip_block_size_minus2"; #else if (pps.getPpsRangeExtension().getLog2MaxTransformSkipBlockSize() != 2 && rextToolsEnabled==DISABLED ) flags+=", log2_max_transform_skip_block_size_minus2"; #endif if (!flags.empty()) { TDecConformanceCheck::getStream() << "the following flags must all be " << (bWantedFlagState ? "1" : "0") << " in the profile '" << features.getProfileFeatures()->pNameString << "' conformance point: " + flags.substr(2) + "\n"; TDecConformanceCheck::finishWarningReport(); } } else { TDecConformanceCheck::checkRange(pps.getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()-2, "log2_max_transform_skip_block_size_minus2", 0, sps.getQuadtreeTULog2MaxSize()-2); } #if DPB_ENCODER_USAGE_CHECK if (features.getProfileFeatures()->extendedPrecisionProcessingFlag != ProfileFeatures::OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->extendedPrecisionProcessingFlag == ProfileFeatures::ENABLED; #else if (features.getProfileFeatures()->extendedPrecisionProcessingFlag != OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->extendedPrecisionProcessingFlag == ENABLED; #endif if (sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag() != bWantedFlagState) { TDecConformanceCheck::getStream() << "extended_precision_processing_flag must be " << (bWantedFlagState ? "1" : "0") << " in the profile '" << features.getProfileFeatures()->pNameString << "' conformance point\n"; TDecConformanceCheck::finishWarningReport(); } } #if DPB_ENCODER_USAGE_CHECK if (features.getProfileFeatures()->chromaQpOffsetListEnabledFlag != ProfileFeatures::OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->chromaQpOffsetListEnabledFlag == ProfileFeatures::ENABLED; #else if (features.getProfileFeatures()->chromaQpOffsetListEnabledFlag != OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->chromaQpOffsetListEnabledFlag == ENABLED; #endif if (pps.getPpsRangeExtension().getChromaQpOffsetListEnabledFlag() != bWantedFlagState) { TDecConformanceCheck::getStream() << "chroma_qp_offset_list_enabled_flag must be " << (bWantedFlagState ? "1" : "0") << " in the profile '" << features.getProfileFeatures()->pNameString << "' conformance point\n"; TDecConformanceCheck::finishWarningReport(); } } else if (pps.getPpsRangeExtension().getChromaQpOffsetListEnabledFlag()) { TDecConformanceCheck::checkRange(pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth(), "diff_cu_chroma_qp_offset_depth", 0, sps.getLog2DiffMaxMinCodingBlockSize()); } #if DPB_ENCODER_USAGE_CHECK if (features.getProfileFeatures()->cabacBypassAlignmentEnabledFlag != ProfileFeatures::OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->cabacBypassAlignmentEnabledFlag == ProfileFeatures::ENABLED; #else if (features.getProfileFeatures()->cabacBypassAlignmentEnabledFlag != OPTIONAL) { const Bool bWantedFlagState = features.getProfileFeatures()->cabacBypassAlignmentEnabledFlag == ENABLED; #endif if (sps.getSpsRangeExtension().getCabacBypassAlignmentEnabledFlag() != bWantedFlagState) { TDecConformanceCheck::getStream() << "cabac_bypass_alignment_enabled_flag must be " << (bWantedFlagState ? "1" : "0") << " in the profile '" << features.getProfileFeatures()->pNameString << "' conformance point\n"; TDecConformanceCheck::finishWarningReport(); } } } Void TDecConformanceCheck::checkSliceActivation(const TComSlice &slice, const InputNALUnit &nalu, const TComPic &pic, const Bool bFirstSliceInStream, const Bool bFirstSliceInSequence, const Bool bFirstSliceInPicture) { const TComSPS &sps=*(slice.getSPS()); const TComPPS &pps=*(slice.getPPS()); if (!doChecking()) return; m_activatedFeatures.activate(sps); if (m_activatedFeatures.getProfileFeatures() == 0 || m_activatedFeatures.getLevelTierFeatures() == 0) { if (m_activatedFeatures.getProfileFeatures() == 0) { getStream() << "Unknown profile/constraint flag combination discovered\n"; } else { getStream() << "Unknown level IDC discovered\n"; } finishWarningReport(); } else { // Most of the parameters have been individually checked prior to this as they were decoded. checkSPS(sps, m_activatedFeatures); // checks SPS limits checkPPS(sps, pps, pic, m_activatedFeatures); // checks PPS limits checkToolAvailability(sps, pps, m_activatedFeatures); if (m_activatedFeatures.getProfileFeatures()->onlyIRAPPictures() && (nalu.m_nalUnitType < NAL_UNIT_CODED_SLICE_BLA_W_LP || nalu.m_nalUnitType> NAL_UNIT_RESERVED_IRAP_VCL23)) { getStream() << "Bad NALU for an intra constrained profile\n"; finishWarningReport(); } if (bFirstSliceInStream || bFirstSliceInSequence || bFirstSliceInPicture) { m_numberOfSlicesInPicture=1; m_bytesInPicture=0; } else { m_numberOfSlicesInPicture++; if (m_numberOfSlicesInPicture > m_activatedFeatures.getLevelTierFeatures()->maxSliceSegmentsPerPicture) { getStream() << "Too many slice segments in the picture\n"; finishWarningReport(); } } // Currently no HRD analysis is made. For now, just ensure access unit fits within the CPB. m_bytesInPicture+=nalu.getBitstream().getFifo().size(); if (m_bytesInPicture*8 > m_activatedFeatures.getCpbSizeInBits()) { getStream() << "Entire access unit must fit within the CPB even if split into multiple decoding units (section C.2.2 Timing of decoding unit arrival)\n"; finishWarningReport(); } } } Void TDecConformanceCheck::checkCtuDecoding(const UInt numUsedBits) { if (numUsedBits > m_activatedFeatures.getMaxRawCtuBits()) { getStream() << "CTU exceeds maximum RAW CTU bits limits.\n"; finishWarningReport(); } } #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecConformance.h000066400000000000000000000222161442026013100215350ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecConformance.h \brief Decoder conformance functions (header) */ #ifndef __TDECCONFORMANCE__ #define __TDECCONFORMANCE__ // This can be enabled externally. Note that this is a PARTIAL CONFORMANCE CHECK - not a full check. More checks may be added later #ifndef DECODER_PARTIAL_CONFORMANCE_CHECK #define DECODER_PARTIAL_CONFORMANCE_CHECK 0 ///< 0 (default) = do not check conformance. 1 = warn if conformance checks fail. 2 = error and quit if conformance checks fail. Note this is only a partial conformance check - not a full conformance check. #endif #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #if DPB_ENCODER_USAGE_CHECK #include "TLibCommon/ProfileLevelTierFeatures.h" #endif #include #include #if DECODER_PARTIAL_CONFORMANCE_CHECK == 2 #include #endif // Forward declarations class TComSlice; #if !DPB_ENCODER_USAGE_CHECK class TComSPS; class TComPPS; #endif class InputNALUnit; class TComPTL; class TComPic; #if !DPB_ENCODER_USAGE_CHECK typedef enum TRISTATE { DISABLED=0, OPTIONAL=1, ENABLED=2 } TRISTATE; typedef enum HBRFACTOREQN { HBR_1 = 0, HBR_1_OR_2 = 1, HBR_12_OR_24 = 2 } HBRFACTOREQN; struct LevelTierFeatures { Level::Name level; UInt maxLumaPs; UInt maxCpb[Level::NUMBER_OF_TIERS]; // in units of CpbVclFactor or CpbNalFactor bits UInt maxSliceSegmentsPerPicture; UInt maxTileRows; UInt maxTileCols; UInt64 maxLumaSr; UInt maxBr[Level::NUMBER_OF_TIERS]; // in units of BrVclFactor or BrNalFactor bits/s UInt minCrBase[Level::NUMBER_OF_TIERS]; UInt getMaxPicWidthInLumaSamples() const; UInt getMaxPicHeightInLumaSamples() const; }; struct ProfileFeatures { Profile::Name profile; const TChar *pNameString; UInt maxBitDepth; ChromaFormat maxChromaFormat; Bool generalIntraConstraintFlag; Bool generalOnePictureOnlyConstraintFlag; TRISTATE generalLowerBitRateConstraint; TRISTATE generalRExtToolsEnabled; TRISTATE extendedPrecisionProcessingFlag; TRISTATE chromaQpOffsetListEnabledFlag; TRISTATE cabacBypassAlignmentEnabledFlag; HBRFACTOREQN hbrFactorEqn; Bool bWavefrontsAndTilesCanBeUsedSimultaneously; UInt minTileColumnWidthInLumaSamples; UInt minTileRowHeightInLumaSamples; Bool bCanUseLevel8p5; UInt cpbVclFactor; UInt cpbNalFactor; // currently not used for checking UInt formatCapabilityFactorx1000; // currently not used for checking UInt minCrScaleFactorx10; // currently not used for checking const LevelTierFeatures *pLevelTiersListInfo; Bool chromaFormatValid(ChromaFormat chFmt) const { return (profile == Profile::MAINREXT || profile == Profile::HIGHTHROUGHPUTREXT) ? chFmt<=maxChromaFormat : (chFmt == maxChromaFormat ); } Bool onlyIRAPPictures() const { return generalIntraConstraintFlag; } UInt getHbrFactor(Bool bLowerBitRateConstraintFlag) const // currently not used for checking { return hbrFactorEqn==HBR_1_OR_2 ? (2-(bLowerBitRateConstraintFlag?1:0)) : (hbrFactorEqn==HBR_12_OR_24 ? 12*(2-(bLowerBitRateConstraintFlag?1:0)) : 1); } }; class ProfileLevelTierFeatures { private: const ProfileFeatures *m_pProfile; const LevelTierFeatures *m_pLevelTier; UInt m_hbrFactor; // currently not used for checking Level::Tier m_tier; UInt m_maxRawCtuBits; public: ProfileLevelTierFeatures() : m_pProfile(0), m_pLevelTier(0), m_hbrFactor(0), m_tier(Level::MAIN), m_maxRawCtuBits(0) { } Void activate(const TComSPS &sps); const ProfileFeatures *getProfileFeatures() const { return m_pProfile; } const LevelTierFeatures *getLevelTierFeatures() const { return m_pLevelTier; } Level::Tier getTier() const { return m_tier; } UInt64 getCpbSizeInBits() const { return (m_pLevelTier!=0 && m_pProfile!=0) ? UInt64(m_pProfile->cpbVclFactor) * m_pLevelTier->maxCpb[m_tier?1:0] : UInt64(0); } Double getMinCr() const { return (m_pLevelTier!=0 && m_pProfile!=0) ? (m_pProfile->minCrScaleFactorx10 * m_pLevelTier->minCrBase[m_tier?1:0])/10.0 : 0.0 ; } // currently not used for checking UInt getMaxRawCtuBits() const { return m_maxRawCtuBits; } }; #endif class TDecConformanceCheck { private: #if MCTS_ENC_CHECK Bool m_tmctsCheckEnabled; #endif #if DECODER_PARTIAL_CONFORMANCE_CHECK UInt m_numberOfSlicesInPicture; UInt64 m_bytesInPicture; #endif ProfileLevelTierFeatures m_activatedFeatures; public: // Static member functions static inline Bool doChecking() { return DECODER_PARTIAL_CONFORMANCE_CHECK != 0; } static UInt getMinLog2CtbSize(const TComPTL &ptl, UInt layerPlus1=0); static UInt getMaxLog2CtbSize(const TComPTL &ptl, UInt layerPlus1=0); #if DECODER_PARTIAL_CONFORMANCE_CHECK == 0 static inline std::ostream &getStream() { return std::cout; } static inline Void finishWarningReport() { } template static Void checkRange(const T& , const TChar *, const T& , const T& ) { } #else static inline std::ostream &getStream() { #if DECODER_PARTIAL_CONFORMANCE_CHECK == 1 std::cout << "WARNING: Conformance failure - "; return std::cout; #else std::cerr << "ERROR: Conformance failure - "; return std::cerr; #endif } static inline Void finishWarningReport() { #if DECODER_PARTIAL_CONFORMANCE_CHECK == 2 exit(1); #endif } template static Void checkRange(const T& val, const TChar *name, const T& minValInclusive, const T& maxValInclusive) { if (valmaxValInclusive) { getStream() << name << " must be in the range of " << minValInclusive << " to " << maxValInclusive << " (inclusive) - decoded value of " << val << "\n"; finishWarningReport(); } } #endif // Member functions TDecConformanceCheck(); #if DECODER_PARTIAL_CONFORMANCE_CHECK == 0 Void checkSliceActivation(const TComSlice &/*slice*/, const InputNALUnit &/*nalu*/, const TComPic &/*pic*/, const Bool /*bFirstSliceInStream*/, const Bool /*bFirstSliceInSequence*/, const Bool /*bFirstSliceInPicture*/) { } Void checkCtuDecoding(const UInt numUsedBits) { } #else Void checkSliceActivation(const TComSlice &slice, const InputNALUnit &nalu, const TComPic &pic, const Bool bFirstSliceInStream, const Bool bFirstSliceInSequence, const Bool bFirstSliceInPicture); Void checkCtuDecoding(const UInt numUsedBits); #endif #if MCTS_ENC_CHECK Void enableTMctsCheck(Bool enabled) { m_tmctsCheckEnabled = enabled; }; Bool getTMctsCheck() const { return m_tmctsCheckEnabled; } Void flagTMctsError(const char *error) { fprintf(stderr, "TMCTS check error: %s\n", error); } #endif }; #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecCu.cpp000066400000000000000000000736631442026013100202210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecCu.cpp \brief CU decoder class */ #include "TDecCu.h" #include "TLibCommon/TComTU.h" #include "TLibCommon/TComPrediction.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TDecCu::TDecCu() { m_ppcYuvResi = NULL; m_ppcYuvReco = NULL; m_ppcCU = NULL; } TDecCu::~TDecCu() { } #if MCTS_ENC_CHECK Void TDecCu::init( TDecEntropy* pcEntropyDecoder, TComTrQuant* pcTrQuant, TComPrediction* pcPrediction, TDecConformanceCheck* pConformanceCheck) #else Void TDecCu::init(TDecEntropy* pcEntropyDecoder, TComTrQuant* pcTrQuant, TComPrediction* pcPrediction) #endif { m_pcEntropyDecoder = pcEntropyDecoder; m_pcTrQuant = pcTrQuant; m_pcPrediction = pcPrediction; #if MCTS_ENC_CHECK m_pConformanceCheck = pConformanceCheck; #endif } /** \param uiMaxDepth total number of allowable depth \param uiMaxWidth largest CU width \param uiMaxHeight largest CU height \param chromaFormatIDC chroma format */ Void TDecCu::create( UInt uiMaxDepth, UInt uiMaxWidth, UInt uiMaxHeight, ChromaFormat chromaFormatIDC ) { m_uiMaxDepth = uiMaxDepth+1; m_ppcYuvResi = new TComYuv*[m_uiMaxDepth-1]; m_ppcYuvReco = new TComYuv*[m_uiMaxDepth-1]; m_ppcCU = new TComDataCU*[m_uiMaxDepth-1]; for ( UInt ui = 0; ui < m_uiMaxDepth-1; ui++ ) { UInt uiNumPartitions = 1<<( ( m_uiMaxDepth - ui - 1 )<<1 ); UInt uiWidth = uiMaxWidth >> ui; UInt uiHeight = uiMaxHeight >> ui; // The following arrays (m_ppcYuvResi, m_ppcYuvReco and m_ppcCU) are only required for CU depths // although data is allocated for all possible depths of the CU/TU tree except the last. // Since the TU tree will always include at least one additional depth greater than the CU tree, // there will be enough entries for these arrays. // (Section 7.4.3.2: "The CVS shall not contain data that result in (Log2MinTrafoSize) MinTbLog2SizeY // greater than or equal to MinCbLog2SizeY") // TODO: tidy the array allocation given the above comment. m_ppcYuvResi[ui] = new TComYuv; m_ppcYuvResi[ui]->create( uiWidth, uiHeight, chromaFormatIDC ); m_ppcYuvReco[ui] = new TComYuv; m_ppcYuvReco[ui]->create( uiWidth, uiHeight, chromaFormatIDC ); m_ppcCU [ui] = new TComDataCU; m_ppcCU [ui]->create( chromaFormatIDC, uiNumPartitions, uiWidth, uiHeight, true, uiMaxWidth >> (m_uiMaxDepth - 1) ); } m_bDecodeDQP = false; m_IsChromaQpAdjCoded = false; // initialize partition order. UInt* piTmp = &g_auiZscanToRaster[0]; initZscanToRaster(m_uiMaxDepth, 1, 0, piTmp); initRasterToZscan( uiMaxWidth, uiMaxHeight, m_uiMaxDepth ); // initialize conversion matrix from partition index to pel initRasterToPelXY( uiMaxWidth, uiMaxHeight, m_uiMaxDepth ); } Void TDecCu::destroy() { for ( UInt ui = 0; ui < m_uiMaxDepth-1; ui++ ) { m_ppcYuvResi[ui]->destroy(); delete m_ppcYuvResi[ui]; m_ppcYuvResi[ui] = NULL; m_ppcYuvReco[ui]->destroy(); delete m_ppcYuvReco[ui]; m_ppcYuvReco[ui] = NULL; m_ppcCU [ui]->destroy(); delete m_ppcCU [ui]; m_ppcCU [ui] = NULL; } delete [] m_ppcYuvResi; m_ppcYuvResi = NULL; delete [] m_ppcYuvReco; m_ppcYuvReco = NULL; delete [] m_ppcCU ; m_ppcCU = NULL; } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** Parse a CTU. \param pCtu [in/out] pointer to CTU data structure \param isLastCtuOfSliceSegment [out] true, if last CTU of the slice segment */ Void TDecCu::decodeCtu( TComDataCU* pCtu, Bool& isLastCtuOfSliceSegment ) { if ( pCtu->getSlice()->getPPS()->getUseDQP() ) { setdQPFlag(true); } if ( pCtu->getSlice()->getUseChromaQpAdj() ) { setIsChromaQpAdjCoded(true); } // start from the top level CU xDecodeCU( pCtu, 0, 0, isLastCtuOfSliceSegment); } /** Decoding process for a CTU. \param pCtu [in/out] pointer to CTU data structure */ Void TDecCu::decompressCtu( TComDataCU* pCtu ) { xDecompressCU( pCtu, 0, 0 ); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== //! decode end-of-slice flag Bool TDecCu::xDecodeSliceEnd( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiIsLastCtuOfSliceSegment; if (pcCU->isLastSubCUOfCtu(uiAbsPartIdx)) { m_pcEntropyDecoder->decodeTerminatingBit( uiIsLastCtuOfSliceSegment ); } else { uiIsLastCtuOfSliceSegment=0; } return uiIsLastCtuOfSliceSegment>0; } //! decode CU block recursively Void TDecCu::xDecodeCU( TComDataCU*const pcCU, const UInt uiAbsPartIdx, const UInt uiDepth, Bool &isLastCtuOfSliceSegment) { TComPic* pcPic = pcCU->getPic(); const TComSPS &sps = pcPic->getPicSym()->getSPS(); const TComPPS &pps = pcPic->getPicSym()->getPPS(); const UInt maxCuWidth = sps.getMaxCUWidth(); const UInt maxCuHeight= sps.getMaxCUHeight(); UInt uiCurNumParts = pcPic->getNumPartitionsInCtu() >> (uiDepth<<1); UInt uiQNumParts = uiCurNumParts>>2; Bool bBoundary = false; UInt uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; UInt uiRPelX = uiLPelX + (maxCuWidth>>uiDepth) - 1; UInt uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ]; UInt uiBPelY = uiTPelY + (maxCuHeight>>uiDepth) - 1; if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) ) { m_pcEntropyDecoder->decodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth ); } else { bBoundary = true; } if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary ) { UInt uiIdx = uiAbsPartIdx; if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP()) { setdQPFlag(true); pcCU->setQPSubParts( pcCU->getRefQP(uiAbsPartIdx), uiAbsPartIdx, uiDepth ); // set QP to default QP } if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcCU->getSlice()->getUseChromaQpAdj() ) { setIsChromaQpAdjCoded(true); } for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ ) { uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ]; uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ]; if ( !isLastCtuOfSliceSegment && ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ) { xDecodeCU( pcCU, uiIdx, uiDepth+1, isLastCtuOfSliceSegment ); } else { pcCU->setOutsideCUPart( uiIdx, uiDepth+1 ); } uiIdx += uiQNumParts; } if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP()) { if ( getdQPFlag() ) { UInt uiQPSrcPartIdx = uiAbsPartIdx; pcCU->setQPSubParts( pcCU->getRefQP( uiQPSrcPartIdx ), uiAbsPartIdx, uiDepth ); // set QP to default QP } } return; } if( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP()) { setdQPFlag(true); pcCU->setQPSubParts( pcCU->getRefQP(uiAbsPartIdx), uiAbsPartIdx, uiDepth ); // set QP to default QP } if( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcCU->getSlice()->getUseChromaQpAdj() ) { setIsChromaQpAdjCoded(true); } if (pps.getTransquantBypassEnabledFlag()) { m_pcEntropyDecoder->decodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx, uiDepth ); } // decode CU mode and the partition size if( !pcCU->getSlice()->isIntra()) { m_pcEntropyDecoder->decodeSkipFlag( pcCU, uiAbsPartIdx, uiDepth ); } if( pcCU->isSkipped(uiAbsPartIdx) ) { m_ppcCU[uiDepth]->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_0 ); m_ppcCU[uiDepth]->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_1 ); TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS]; Int numValidMergeCand = 0; for( UInt ui = 0; ui < m_ppcCU[uiDepth]->getSlice()->getMaxNumMergeCand(); ++ui ) { uhInterDirNeighbours[ui] = 0; } m_pcEntropyDecoder->decodeMergeIndex( pcCU, 0, uiAbsPartIdx, uiDepth ); UInt uiMergeIndex = pcCU->getMergeIndex(uiAbsPartIdx); #if MCTS_ENC_CHECK UInt numSpatialMergeCandidates = 0; m_ppcCU[uiDepth]->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates, uiMergeIndex ); if ( m_pConformanceCheck->getTMctsCheck() && m_ppcCU[uiDepth]->isLastColumnCTUInTile() && (uiMergeIndex >= numSpatialMergeCandidates) ) { m_pConformanceCheck->flagTMctsError("Merge Index using non-spatial merge candidate (Skip)"); } #else m_ppcCU[uiDepth]->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex ); #endif pcCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeIndex], uiAbsPartIdx, 0, uiDepth ); TComMv cTmpMv( 0, 0 ); for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { pcCU->setMVPIdxSubParts( 0, RefPicList( uiRefListIdx ), uiAbsPartIdx, 0, uiDepth); pcCU->setMVPNumSubParts( 0, RefPicList( uiRefListIdx ), uiAbsPartIdx, 0, uiDepth); pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvd( cTmpMv, SIZE_2Nx2N, uiAbsPartIdx, uiDepth ); pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvField( cMvFieldNeighbours[ 2*uiMergeIndex + uiRefListIdx ], SIZE_2Nx2N, uiAbsPartIdx, uiDepth ); } } xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment ); return; } m_pcEntropyDecoder->decodePredMode( pcCU, uiAbsPartIdx, uiDepth ); m_pcEntropyDecoder->decodePartSize( pcCU, uiAbsPartIdx, uiDepth ); if (pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N ) { m_pcEntropyDecoder->decodeIPCMInfo( pcCU, uiAbsPartIdx, uiDepth ); if(pcCU->getIPCMFlag(uiAbsPartIdx)) { xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment ); return; } } // prediction mode ( Intra : direction mode, Inter : Mv, reference idx ) m_pcEntropyDecoder->decodePredInfo( pcCU, uiAbsPartIdx, uiDepth, m_ppcCU[uiDepth]); // Coefficient decoding Bool bCodeDQP = getdQPFlag(); Bool isChromaQpAdjCoded = getIsChromaQpAdjCoded(); m_pcEntropyDecoder->decodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, isChromaQpAdjCoded ); setIsChromaQpAdjCoded( isChromaQpAdjCoded ); setdQPFlag( bCodeDQP ); xFinishDecodeCU( pcCU, uiAbsPartIdx, uiDepth, isLastCtuOfSliceSegment ); } Void TDecCu::xFinishDecodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool &isLastCtuOfSliceSegment) { if( pcCU->getSlice()->getPPS()->getUseDQP()) { pcCU->setQPSubParts( getdQPFlag()?pcCU->getRefQP(uiAbsPartIdx):pcCU->getCodedQP(), uiAbsPartIdx, uiDepth ); // set QP } if (pcCU->getSlice()->getUseChromaQpAdj() && !getIsChromaQpAdjCoded()) { pcCU->setChromaQpAdjSubParts( pcCU->getCodedChromaQpAdj(), uiAbsPartIdx, uiDepth ); // set QP } isLastCtuOfSliceSegment = xDecodeSliceEnd( pcCU, uiAbsPartIdx ); } Void TDecCu::xDecompressCU( TComDataCU* pCtu, UInt uiAbsPartIdx, UInt uiDepth ) { TComPic* pcPic = pCtu->getPic(); TComSlice * pcSlice = pCtu->getSlice(); const TComSPS &sps=*(pcSlice->getSPS()); Bool bBoundary = false; UInt uiLPelX = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; UInt uiRPelX = uiLPelX + (sps.getMaxCUWidth()>>uiDepth) - 1; UInt uiTPelY = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ]; UInt uiBPelY = uiTPelY + (sps.getMaxCUHeight()>>uiDepth) - 1; if( ( uiRPelX >= sps.getPicWidthInLumaSamples() ) || ( uiBPelY >= sps.getPicHeightInLumaSamples() ) ) { bBoundary = true; } if( ( ( uiDepth < pCtu->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary ) { UInt uiNextDepth = uiDepth + 1; UInt uiQNumParts = pCtu->getTotalNumPart() >> (uiNextDepth<<1); UInt uiIdx = uiAbsPartIdx; for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++ ) { uiLPelX = pCtu->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ]; uiTPelY = pCtu->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ]; if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ) { xDecompressCU(pCtu, uiIdx, uiNextDepth ); } uiIdx += uiQNumParts; } return; } // Residual reconstruction m_ppcYuvResi[uiDepth]->clear(); m_ppcCU[uiDepth]->copySubCU( pCtu, uiAbsPartIdx ); switch( m_ppcCU[uiDepth]->getPredictionMode(0) ) { case MODE_INTER: xReconInter( m_ppcCU[uiDepth], uiDepth ); break; case MODE_INTRA: xReconIntraQT( m_ppcCU[uiDepth], uiDepth ); break; default: assert(0); break; } #if DEBUG_STRING const PredMode predMode=m_ppcCU[uiDepth]->getPredictionMode(0); if (DebugOptionList::DebugString_Structure.getInt()&DebugStringGetPredModeMask(predMode)) { PartSize eSize=m_ppcCU[uiDepth]->getPartitionSize(0); std::ostream &ss(std::cout); ss <<"###: " << (predMode==MODE_INTRA?"Intra ":"Inter ") << partSizeToString[eSize] << " CU at " << m_ppcCU[uiDepth]->getCUPelX() << ", " << m_ppcCU[uiDepth]->getCUPelY() << " width=" << UInt(m_ppcCU[uiDepth]->getWidth(0)) << std::endl; } #endif if ( m_ppcCU[uiDepth]->isLosslessCoded(0) && (m_ppcCU[uiDepth]->getIPCMFlag(0) == false)) { xFillPCMBuffer(m_ppcCU[uiDepth], uiDepth); } xCopyToPic( m_ppcCU[uiDepth], pcPic, uiAbsPartIdx, uiDepth ); } Void TDecCu::xReconInter( TComDataCU* pcCU, UInt uiDepth ) { // inter prediction #if MCTS_ENC_CHECK if (m_pConformanceCheck->getTMctsCheck() && !m_pcPrediction->checkTMctsMvp(pcCU)) { m_pConformanceCheck->flagTMctsError("motion vector across tile boundaries"); } #endif m_pcPrediction->motionCompensation( pcCU, m_ppcYuvReco[uiDepth] ); #if DEBUG_STRING const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTER); if (DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) { printBlockToStream(std::cout, "###inter-pred: ", *(m_ppcYuvReco[uiDepth])); } #endif // inter recon xDecodeInterTexture( pcCU, uiDepth ); #if DEBUG_STRING if (DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) { printBlockToStream(std::cout, "###inter-resi: ", *(m_ppcYuvResi[uiDepth])); } #endif // clip for only non-zero cbp case if ( pcCU->getQtRootCbf( 0) ) { m_ppcYuvReco[uiDepth]->addClip( m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], 0, pcCU->getWidth( 0 ), pcCU->getSlice()->getSPS()->getBitDepths() ); } else { m_ppcYuvReco[uiDepth]->copyPartToPartYuv( m_ppcYuvReco[uiDepth],0, pcCU->getWidth( 0 ),pcCU->getHeight( 0 )); } #if DEBUG_STRING if (DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) { printBlockToStream(std::cout, "###inter-reco: ", *(m_ppcYuvReco[uiDepth])); } #endif } Void TDecCu::xIntraRecBlk( TComYuv* pcRecoYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, const ComponentID compID, TComTU &rTu) { if (!rTu.ProcessComponentSection(compID)) { return; } const Bool bIsLuma = isLuma(compID); TComDataCU *pcCU = rTu.getCU(); const TComSPS &sps=*(pcCU->getSlice()->getSPS()); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const TComRectangle &tuRect =rTu.getRect(compID); const UInt uiWidth = tuRect.width; const UInt uiHeight = tuRect.height; const UInt uiStride = pcRecoYuv->getStride (compID); Pel* piPred = pcPredYuv->getAddr( compID, uiAbsPartIdx ); const ChromaFormat chFmt = rTu.GetChromaFormat(); if (uiWidth != uiHeight) { //------------------------------------------------ //split at current level if dividing into square sub-TUs TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID); //recurse further do { xIntraRecBlk(pcRecoYuv, pcPredYuv, pcResiYuv, compID, subTURecurse); } while (subTURecurse.nextSection(rTu)); //------------------------------------------------ return; } const UInt uiChPredMode = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx ); const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize())); const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode; const UInt uiChFinalMode = ((chFmt == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; //===== init availability pattern ===== const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag()); #if DEBUG_STRING std::ostream &ss(std::cout); #endif DEBUG_STRING_NEW(sTemp) m_pcPrediction->initIntraPatternChType( rTu, compID, bUseFilteredPredictions DEBUG_STRING_PASS_INTO(sTemp) ); //===== get prediction signal ===== m_pcPrediction->predIntraAng( compID, uiChFinalMode, 0 /* Decoder does not have an original image */, 0, piPred, uiStride, rTu, bUseFilteredPredictions ); #if DEBUG_STRING ss << sTemp; #endif //===== inverse transform ===== Pel* piResi = pcResiYuv->getAddr( compID, uiAbsPartIdx ); TCoeff* pcCoeff = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID);//( uiNumCoeffInc * uiAbsPartIdx ); const QpParam cQP(*pcCU, compID); DEBUG_STRING_NEW(sDebug); #if DEBUG_STRING const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA); std::string *psDebug=(DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ? &sDebug : 0; #endif if (pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0) { m_pcTrQuant->invTransformNxN( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) ); } else { for (UInt y = 0; y < uiHeight; y++) { for (UInt x = 0; x < uiWidth; x++) { piResi[(y * uiStride) + x] = 0; } } } #if DEBUG_STRING if (psDebug) { ss << (*psDebug); } #endif //===== reconstruction ===== const UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride(compID); const Bool useCrossComponentPrediction = isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(uiAbsPartIdx, compID) != 0); const Pel* pResiLuma = pcResiYuv->getAddr( COMPONENT_Y, uiAbsPartIdx ); const Int strideLuma = pcResiYuv->getStride( COMPONENT_Y ); Pel* pPred = piPred; Pel* pResi = piResi; Pel* pReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx ); Pel* pRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx ); #if DEBUG_STRING const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); if (bDebugPred || bDebugResi || bDebugReco) { ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << std::endl; } #endif const Int clipbd = sps.getBitDepth(toChannelType(compID)); #if O0043_BEST_EFFORT_DECODING const Int bitDepthDelta = sps.getStreamBitDepth(toChannelType(compID)) - clipbd; #endif if( useCrossComponentPrediction ) { TComTrQuant::crossComponentPrediction( rTu, compID, pResiLuma, piResi, piResi, uiWidth, uiHeight, strideLuma, uiStride, uiStride, true ); } for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { #if DEBUG_STRING if (bDebugPred || bDebugResi || bDebugReco) { ss << "###: "; } if (bDebugPred) { ss << " - pred: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pPred[ uiX ] << ", "; } } if (bDebugResi) { ss << " - resi: "; } #endif for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { #if DEBUG_STRING if (bDebugResi) { ss << pResi[ uiX ] << ", "; } #endif #if O0043_BEST_EFFORT_DECODING pReco [ uiX ] = ClipBD( rightShiftEvenRounding(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), clipbd ); #else pReco [ uiX ] = ClipBD( pPred[ uiX ] + pResi[ uiX ], clipbd ); #endif pRecIPred[ uiX ] = pReco[ uiX ]; } #if DEBUG_STRING if (bDebugReco) { ss << " - reco: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pReco[ uiX ] << ", "; } } if (bDebugPred || bDebugResi || bDebugReco) { ss << "\n"; } #endif pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecIPred += uiRecIPredStride; } } Void TDecCu::xReconIntraQT( TComDataCU* pcCU, UInt uiDepth ) { if (pcCU->getIPCMFlag(0)) { xReconPCM( pcCU, uiDepth ); return; } const UInt numChType = pcCU->getPic()->getChromaFormat()!=CHROMA_400 ? 2 : 1; for (UInt chType=CHANNEL_TYPE_LUMA; chTypegetPic()->getChromaFormat()) : true; const UInt uiInitTrDepth = ( pcCU->getPartitionSize(0) != SIZE_2Nx2N && NxNPUHas4Parts ? 1 : 0 ); TComTURecurse tuRecurseCU(pcCU, 0); TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT); do { xIntraRecQT( m_ppcYuvReco[uiDepth], m_ppcYuvReco[uiDepth], m_ppcYuvResi[uiDepth], chanType, tuRecurseWithPU ); } while (tuRecurseWithPU.nextSection(tuRecurseCU)); } } /** Function for deriving reconstructed PU/CU chroma samples with QTree structure * \param pcRecoYuv pointer to reconstructed sample arrays * \param pcPredYuv pointer to prediction sample arrays * \param pcResiYuv pointer to residue sample arrays * \param chType texture channel type (luma/chroma) * \param rTu reference to transform data * \ This function derives reconstructed PU/CU chroma samples with QTree recursive structure */ Void TDecCu::xIntraRecQT(TComYuv* pcRecoYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, const ChannelType chType, TComTU &rTu) { UInt uiTrDepth = rTu.GetTransformDepthRel(); TComDataCU *pcCU = rTu.getCU(); UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); if( uiTrMode == uiTrDepth ) { if (isLuma(chType)) { xIntraRecBlk( pcRecoYuv, pcPredYuv, pcResiYuv, COMPONENT_Y, rTu ); } else { const UInt numValidComp=getNumberValidComponents(rTu.GetChromaFormat()); for(UInt compID=COMPONENT_Cb; compIDgetCtuRsAddr(); m_ppcYuvReco[uiDepth]->copyToPicYuv ( pcPic->getPicYuvRec (), uiCtuRsAddr, uiZorderIdx ); return; } Void TDecCu::xDecodeInterTexture ( TComDataCU* pcCU, UInt uiDepth ) { TComTURecurse tuRecur(pcCU, 0, uiDepth); for(UInt ch=0; chgetPic()->getNumberValidComponents(); ch++) { const ComponentID compID=ComponentID(ch); DEBUG_STRING_OUTPUT(std::cout, debug_reorder_data_inter_token[compID]) m_pcTrQuant->invRecurTransformNxN ( compID, m_ppcYuvResi[uiDepth], tuRecur ); } DEBUG_STRING_OUTPUT(std::cout, debug_reorder_data_inter_token[MAX_NUM_COMPONENT]) } /** Function for deriving reconstructed luma/chroma samples of a PCM mode CU. * \param pcCU pointer to current CU * \param uiPartIdx part index * \param piPCM pointer to PCM code arrays * \param piReco pointer to reconstructed sample arrays * \param uiStride stride of reconstructed sample arrays * \param uiWidth CU width * \param uiHeight CU height * \param compID colour component ID * \returns Void */ Void TDecCu::xDecodePCMTexture( TComDataCU* pcCU, const UInt uiPartIdx, const Pel *piPCM, Pel* piReco, const UInt uiStride, const UInt uiWidth, const UInt uiHeight, const ComponentID compID) { Pel* piPicReco = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiPartIdx); const UInt uiPicStride = pcCU->getPic()->getPicYuvRec()->getStride(compID); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiPcmLeftShiftBit = sps.getBitDepth(toChannelType(compID)) - sps.getPCMBitDepth(toChannelType(compID)); for(UInt uiY = 0; uiY < uiHeight; uiY++ ) { for(UInt uiX = 0; uiX < uiWidth; uiX++ ) { piReco[uiX] = (piPCM[uiX] << uiPcmLeftShiftBit); piPicReco[uiX] = piReco[uiX]; } piPCM += uiWidth; piReco += uiStride; piPicReco += uiPicStride; } } /** Function for reconstructing a PCM mode CU. * \param pcCU pointer to current CU * \param uiDepth CU Depth * \returns Void */ Void TDecCu::xReconPCM( TComDataCU* pcCU, UInt uiDepth ) { const UInt maxCuWidth = pcCU->getSlice()->getSPS()->getMaxCUWidth(); const UInt maxCuHeight = pcCU->getSlice()->getSPS()->getMaxCUHeight(); for (UInt ch=0; ch < pcCU->getPic()->getNumberValidComponents(); ch++) { const ComponentID compID = ComponentID(ch); const UInt width = (maxCuWidth >>(uiDepth+m_ppcYuvResi[uiDepth]->getComponentScaleX(compID))); const UInt height = (maxCuHeight>>(uiDepth+m_ppcYuvResi[uiDepth]->getComponentScaleY(compID))); const UInt stride = m_ppcYuvResi[uiDepth]->getStride(compID); Pel * pPCMChannel = pcCU->getPCMSample(compID); Pel * pRecChannel = m_ppcYuvReco[uiDepth]->getAddr(compID); xDecodePCMTexture( pcCU, 0, pPCMChannel, pRecChannel, stride, width, height, compID ); } } /** Function for filling the PCM buffer of a CU using its reconstructed sample array * \param pCU pointer to current CU * \param depth CU Depth */ Void TDecCu::xFillPCMBuffer(TComDataCU* pCU, UInt depth) { const ChromaFormat format = pCU->getPic()->getChromaFormat(); const UInt numValidComp = getNumberValidComponents(format); const UInt maxCuWidth = pCU->getSlice()->getSPS()->getMaxCUWidth(); const UInt maxCuHeight = pCU->getSlice()->getSPS()->getMaxCUHeight(); for (UInt componentIndex = 0; componentIndex < numValidComp; componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt width = maxCuWidth >> (depth + getComponentScaleX(component, format)); const UInt height = maxCuHeight >> (depth + getComponentScaleY(component, format)); Pel *source = m_ppcYuvReco[depth]->getAddr(component, 0, width); Pel *destination = pCU->getPCMSample(component); const UInt sourceStride = m_ppcYuvReco[depth]->getStride(component); for (Int line = 0; line < height; line++) { for (Int column = 0; column < width; column++) { destination[column] = source[column]; } source += sourceStride; destination += width; } } } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecCu.h000066400000000000000000000126601442026013100176540ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecCu.h \brief CU decoder class (header) */ #ifndef __TDECCU__ #define __TDECCU__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/TComTrQuant.h" #include "TDecEntropy.h" #include "TDecConformance.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// CU decoder class class TDecCu { private: UInt m_uiMaxDepth; ///< max. number of depth TComYuv** m_ppcYuvResi; ///< array of residual buffer TComYuv** m_ppcYuvReco; ///< array of prediction & reconstruction buffer TComDataCU** m_ppcCU; ///< CU data array // access channel TComTrQuant* m_pcTrQuant; TComPrediction* m_pcPrediction; TDecEntropy* m_pcEntropyDecoder; #if MCTS_ENC_CHECK TDecConformanceCheck* m_pConformanceCheck; #endif Bool m_bDecodeDQP; Bool m_IsChromaQpAdjCoded; public: TDecCu(); virtual ~TDecCu(); /// initialize access channels #if MCTS_ENC_CHECK Void init (TDecEntropy* pcEntropyDecoder, TComTrQuant* pcTrQuant, TComPrediction* pcPrediction, TDecConformanceCheck* pConformanceCheck); #else Void init ( TDecEntropy* pcEntropyDecoder, TComTrQuant* pcTrQuant, TComPrediction* pcPrediction ); #endif /// create internal buffers Void create ( UInt uiMaxDepth, UInt uiMaxWidth, UInt uiMaxHeight, ChromaFormat chromaFormatIDC ); /// destroy internal buffers Void destroy (); /// decode Ctu information Void decodeCtu ( TComDataCU* pCtu, Bool &isLastCtuOfSliceSegment ); /// reconstruct Ctu information Void decompressCtu ( TComDataCU* pCtu ); protected: Void xDecodeCU ( TComDataCU* const pcCU, const UInt uiAbsPartIdx, const UInt uiDepth, Bool &isLastCtuOfSliceSegment); Void xFinishDecodeCU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool &isLastCtuOfSliceSegment); Bool xDecodeSliceEnd ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void xDecompressCU ( TComDataCU* pCtu, UInt uiAbsPartIdx, UInt uiDepth ); Void xReconInter ( TComDataCU* pcCU, UInt uiDepth ); Void xReconIntraQT ( TComDataCU* pcCU, UInt uiDepth ); Void xIntraRecBlk ( TComYuv* pcRecoYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, const ComponentID component, TComTU &rTu ); Void xIntraRecQT ( TComYuv* pcRecoYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, const ChannelType chType, TComTU &rTu ); Void xReconPCM ( TComDataCU* pcCU, UInt uiDepth ); Void xDecodeInterTexture ( TComDataCU* pcCU, UInt uiDepth ); Void xDecodePCMTexture ( TComDataCU* pcCU, const UInt uiPartIdx, const Pel *piPCM, Pel* piReco, const UInt uiStride, const UInt uiWidth, const UInt uiHeight, const ComponentID compID); Void xCopyToPic ( TComDataCU* pcCU, TComPic* pcPic, UInt uiZorderIdx, UInt uiDepth ); Bool getdQPFlag () { return m_bDecodeDQP; } Void setdQPFlag ( Bool b ) { m_bDecodeDQP = b; } Bool getIsChromaQpAdjCoded () { return m_IsChromaQpAdjCoded; } Void setIsChromaQpAdjCoded ( Bool b ) { m_IsChromaQpAdjCoded = b; } Void xFillPCMBuffer (TComDataCU* pCU, UInt depth); }; //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecEntropy.cpp000066400000000000000000000566161442026013100213110ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecEntropy.cpp \brief entropy decoder class */ #include "TDecEntropy.h" #include "TLibCommon/TComTU.h" #include "TLibCommon/TComPrediction.h" #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST #include "../TLibCommon/Debug.h" static const Bool bDebugRQT = DebugOptionList::DebugRQT.getInt()!=0; static const Bool bDebugPredEnabled = DebugOptionList::DebugPred.getInt()!=0; #endif //! \ingroup TLibDecoder //! \{ Void TDecEntropy::setEntropyDecoder ( TDecEntropyIf* p ) { m_pcEntropyDecoderIf = p; } #include "TLibCommon/TComSampleAdaptiveOffset.h" Void TDecEntropy::decodeSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parseSkipFlag( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodeCUTransquantBypassFlag(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parseCUTransquantBypassFlag( pcCU, uiAbsPartIdx, uiDepth ); } /** decode merge flag * \param pcSubCU * \param uiAbsPartIdx * \param uiDepth * \param uiPUIdx * \returns Void */ Void TDecEntropy::decodeMergeFlag( TComDataCU* pcSubCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ) { // at least one merge candidate exists m_pcEntropyDecoderIf->parseMergeFlag( pcSubCU, uiAbsPartIdx, uiDepth, uiPUIdx ); } /** decode merge index * \param pcCU * \param uiPartIdx * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TDecEntropy::decodeMergeIndex( TComDataCU* pcCU, UInt uiPartIdx, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiMergeIndex = 0; m_pcEntropyDecoderIf->parseMergeIndex( pcCU, uiMergeIndex ); pcCU->setMergeIndexSubParts( uiMergeIndex, uiAbsPartIdx, uiPartIdx, uiDepth ); } Void TDecEntropy::decodeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parseSplitFlag( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodePredMode( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parsePredMode( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodePartSize( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parsePartSize( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodePredInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComDataCU* pcSubCU ) { if( pcCU->isIntra( uiAbsPartIdx ) ) // If it is Intra mode, encode intra prediction mode. { decodeIntraDirModeLuma ( pcCU, uiAbsPartIdx, uiDepth ); if (pcCU->getPic()->getChromaFormat()!=CHROMA_400) { decodeIntraDirModeChroma( pcCU, uiAbsPartIdx, uiDepth ); if (enable4ChromaPUsInIntraNxNCU(pcCU->getPic()->getChromaFormat()) && pcCU->getPartitionSize( uiAbsPartIdx )==SIZE_NxN) { UInt uiPartOffset = ( pcCU->getPic()->getNumPartitionsInCtu() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; decodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset, uiDepth+1 ); decodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset*2, uiDepth+1 ); decodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset*3, uiDepth+1 ); } } } else // if it is Inter mode, encode motion vector and reference index { decodePUWise( pcCU, uiAbsPartIdx, uiDepth, pcSubCU ); } } /** Parse I_PCM information. * \param pcCU pointer to CUpointer to CU * \param uiAbsPartIdx CU index * \param uiDepth CU depth * \returns Void */ Void TDecEntropy::decodeIPCMInfo( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { if(!pcCU->getSlice()->getSPS()->getUsePCM() || pcCU->getWidth(uiAbsPartIdx) > (1<getSlice()->getSPS()->getPCMLog2MaxSize()) || pcCU->getWidth(uiAbsPartIdx) < (1<getSlice()->getSPS()->getPCMLog2MinSize()) ) { return; } m_pcEntropyDecoderIf->parseIPCMInfo( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodeIntraDirModeLuma ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parseIntraDirLumaAng( pcCU, uiAbsPartIdx, uiDepth ); } Void TDecEntropy::decodeIntraDirModeChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { m_pcEntropyDecoderIf->parseIntraDirChroma( pcCU, uiAbsPartIdx, uiDepth ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPredEnabled) { UInt cdir=pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiAbsPartIdx); if (cdir==36) { cdir=pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx); } printf("coding chroma Intra dir: %d, uiAbsPartIdx: %d, luma dir: %d\n", cdir, uiAbsPartIdx, pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx)); } #endif } /** decode motion information for every PU block. * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param pcSubCU * \returns Void */ Void TDecEntropy::decodePUWise( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComDataCU* pcSubCU ) { PartSize ePartSize = pcCU->getPartitionSize( uiAbsPartIdx ); UInt uiNumPU = ( ePartSize == SIZE_2Nx2N ? 1 : ( ePartSize == SIZE_NxN ? 4 : 2 ) ); UInt uiPUOffset = ( g_auiPUOffset[UInt( ePartSize )] << ( ( pcCU->getSlice()->getSPS()->getMaxTotalCUDepth() - uiDepth ) << 1 ) ) >> 4; TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS]; for ( UInt ui = 0; ui < pcCU->getSlice()->getMaxNumMergeCand(); ui++ ) { uhInterDirNeighbours[ui] = 0; } Int numValidMergeCand = 0; Bool hasMergedCandList = false; #if MCTS_ENC_CHECK UInt numSpatialMergeCandidates = 0; #endif pcSubCU->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_0 ); pcSubCU->copyInterPredInfoFrom( pcCU, uiAbsPartIdx, REF_PIC_LIST_1 ); for ( UInt uiPartIdx = 0, uiSubPartIdx = uiAbsPartIdx; uiPartIdx < uiNumPU; uiPartIdx++, uiSubPartIdx += uiPUOffset ) { decodeMergeFlag( pcCU, uiSubPartIdx, uiDepth, uiPartIdx ); if ( pcCU->getMergeFlag( uiSubPartIdx ) ) { decodeMergeIndex( pcCU, uiPartIdx, uiSubPartIdx, uiDepth ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPredEnabled) { std::cout << "Coded merge flag, CU absPartIdx: " << uiAbsPartIdx << " PU(" << uiPartIdx << ") absPartIdx: " << uiSubPartIdx; std::cout << " merge index: " << (UInt)pcCU->getMergeIndex(uiSubPartIdx) << std::endl; } #endif const UInt uiMergeIndex = pcCU->getMergeIndex(uiSubPartIdx); if ( pcCU->getSlice()->getPPS()->getLog2ParallelMergeLevelMinus2() && ePartSize != SIZE_2Nx2N && pcSubCU->getWidth( 0 ) <= 8 ) { if ( !hasMergedCandList ) { pcSubCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uiDepth ); // temporarily set. #if MCTS_ENC_CHECK numSpatialMergeCandidates = 0; pcSubCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates ); #else pcSubCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand ); #endif pcSubCU->setPartSizeSubParts( ePartSize, 0, uiDepth ); // restore. hasMergedCandList = true; } } else { #if MCTS_ENC_CHECK numSpatialMergeCandidates = 0; pcSubCU->getInterMergeCandidates( uiSubPartIdx-uiAbsPartIdx, uiPartIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates, uiMergeIndex ); #else pcSubCU->getInterMergeCandidates( uiSubPartIdx-uiAbsPartIdx, uiPartIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, uiMergeIndex ); #endif } #if MCTS_ENC_CHECK if (m_pConformanceCheck->getTMctsCheck() && pcSubCU->isLastColumnCTUInTile() && (uiMergeIndex >= numSpatialMergeCandidates) ) { m_pConformanceCheck->flagTMctsError("Merge Index using non-spatial merge candidate (Merge)"); } #endif pcCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeIndex], uiSubPartIdx, uiPartIdx, uiDepth ); TComMv cTmpMv( 0, 0 ); for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { pcCU->setMVPIdxSubParts( 0, RefPicList( uiRefListIdx ), uiSubPartIdx, uiPartIdx, uiDepth); pcCU->setMVPNumSubParts( 0, RefPicList( uiRefListIdx ), uiSubPartIdx, uiPartIdx, uiDepth); pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvd( cTmpMv, ePartSize, uiSubPartIdx, uiDepth, uiPartIdx ); pcCU->getCUMvField( RefPicList( uiRefListIdx ) )->setAllMvField( cMvFieldNeighbours[ 2*uiMergeIndex + uiRefListIdx ], ePartSize, uiSubPartIdx, uiDepth, uiPartIdx ); } } } else { decodeInterDirPU( pcCU, uiSubPartIdx, uiDepth, uiPartIdx ); for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { decodeRefFrmIdxPU( pcCU, uiSubPartIdx, uiDepth, uiPartIdx, RefPicList( uiRefListIdx ) ); decodeMvdPU ( pcCU, uiSubPartIdx, uiDepth, uiPartIdx, RefPicList( uiRefListIdx ) ); decodeMVPIdxPU ( pcSubCU, uiSubPartIdx-uiAbsPartIdx, uiDepth, uiPartIdx, RefPicList( uiRefListIdx ) ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPredEnabled) { std::cout << "refListIdx: " << uiRefListIdx << std::endl; std::cout << "MVD horizontal: " << pcCU->getCUMvField(RefPicList(uiRefListIdx))->getMvd( uiAbsPartIdx ).getHor() << std::endl; std::cout << "MVD vertical: " << pcCU->getCUMvField(RefPicList(uiRefListIdx))->getMvd( uiAbsPartIdx ).getVer() << std::endl; std::cout << "MVPIdxPU: " << pcCU->getMVPIdx(RefPicList( uiRefListIdx ), uiSubPartIdx) << std::endl; std::cout << "InterDir: " << (UInt)pcCU->getInterDir(uiSubPartIdx) << std::endl; } #endif } } } if ( (pcCU->getInterDir(uiSubPartIdx) == 3) && pcSubCU->isBipredRestriction(uiPartIdx) ) { pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMv( TComMv(0,0), ePartSize, uiSubPartIdx, uiDepth, uiPartIdx); pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllRefIdx( -1, ePartSize, uiSubPartIdx, uiDepth, uiPartIdx); pcCU->setInterDirSubParts( 1, uiSubPartIdx, uiPartIdx, uiDepth); } } return; } /** decode inter direction for a PU block * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param uiPartIdx * \returns Void */ Void TDecEntropy::decodeInterDirPU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx ) { UInt uiInterDir; if ( pcCU->getSlice()->isInterP() ) { uiInterDir = 1; } else { m_pcEntropyDecoderIf->parseInterDir( pcCU, uiInterDir, uiAbsPartIdx ); } pcCU->setInterDirSubParts( uiInterDir, uiAbsPartIdx, uiPartIdx, uiDepth ); } Void TDecEntropy::decodeRefFrmIdxPU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ) { Int iRefFrmIdx = 0; Int iParseRefFrmIdx = pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ); if ( pcCU->getSlice()->getNumRefIdx( eRefList ) > 1 && iParseRefFrmIdx ) { m_pcEntropyDecoderIf->parseRefFrmIdx( pcCU, iRefFrmIdx, eRefList ); } else if ( !iParseRefFrmIdx ) { iRefFrmIdx = NOT_VALID; } else { iRefFrmIdx = 0; } PartSize ePartSize = pcCU->getPartitionSize( uiAbsPartIdx ); pcCU->getCUMvField( eRefList )->setAllRefIdx( iRefFrmIdx, ePartSize, uiAbsPartIdx, uiDepth, uiPartIdx ); } /** decode motion vector difference for a PU block * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param uiPartIdx * \param eRefList * \returns Void */ Void TDecEntropy::decodeMvdPU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ) { if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyDecoderIf->parseMvd( pcCU, uiAbsPartIdx, uiPartIdx, uiDepth, eRefList ); } } Void TDecEntropy::decodeMVPIdxPU( TComDataCU* pcSubCU, UInt uiPartAddr, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ) { Int iMVPIdx = -1; TComMv cZeroMv( 0, 0 ); TComMv cMv = cZeroMv; Int iRefIdx = -1; TComCUMvField* pcSubCUMvField = pcSubCU->getCUMvField( eRefList ); AMVPInfo* pAMVPInfo = pcSubCUMvField->getAMVPInfo(); iRefIdx = pcSubCUMvField->getRefIdx(uiPartAddr); cMv = cZeroMv; if ( (pcSubCU->getInterDir(uiPartAddr) & ( 1 << eRefList )) ) { m_pcEntropyDecoderIf->parseMVPIdx( iMVPIdx ); } pcSubCU->fillMvpCand(uiPartIdx, uiPartAddr, eRefList, iRefIdx, pAMVPInfo); #if MCTS_ENC_CHECK if ((iRefIdx >= 0) && m_pConformanceCheck->getTMctsCheck() && pcSubCU->isLastColumnCTUInTile() && (iMVPIdx == pAMVPInfo->numSpatialMVPCandidates)) { m_pConformanceCheck->flagTMctsError("Merge Index using non-spatial merge candidate (AMVP)"); } #endif pcSubCU->setMVPNumSubParts(pAMVPInfo->iN, eRefList, uiPartAddr, uiPartIdx, uiDepth); pcSubCU->setMVPIdxSubParts( iMVPIdx, eRefList, uiPartAddr, uiPartIdx, uiDepth ); if ( iRefIdx >= 0 ) { m_pcPrediction->getMvPredAMVP( pcSubCU, uiPartIdx, uiPartAddr, eRefList, cMv); cMv += pcSubCUMvField->getMvd( uiPartAddr ); } PartSize ePartSize = pcSubCU->getPartitionSize( uiPartAddr ); pcSubCU->getCUMvField( eRefList )->setAllMv(cMv, ePartSize, uiPartAddr, 0, uiPartIdx); } Void TDecEntropy::xDecodeTransform ( Bool& bCodeDQP, Bool& isChromaQpAdjCoded, TComTU &rTu, const Int quadtreeTULog2MinSizeInCU ) { TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const UInt uiDepth=rTu.GetTransformDepthTotal(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); UInt uiSubdiv; const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents(); const Bool bChroma = isChromaEnabled(pcCU->getPic()->getChromaFormat()); const UInt uiLog2TrafoSize = rTu.GetLog2LumaTrSize(); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("x..codeTransform: offsetLuma=%d offsetChroma=%d absPartIdx=%d, uiDepth=%d\n width=%d, height=%d, uiTrIdx=%d, uiInnerQuadIdx=%d\n", rTu.getCoefficientOffset(COMPONENT_Y), rTu.getCoefficientOffset(COMPONENT_Cb), uiAbsPartIdx, uiDepth, rTu.getRect(COMPONENT_Y).width, rTu.getRect(COMPONENT_Y).height, rTu.GetTransformDepthRel(), rTu.GetSectionNumber()); fflush(stdout); } #endif if( pcCU->isIntra(uiAbsPartIdx) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_NxN && uiDepth == pcCU->getDepth(uiAbsPartIdx) ) { uiSubdiv = 1; } else if( (pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) && (pcCU->isInter(uiAbsPartIdx)) && ( pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N ) && (uiDepth == pcCU->getDepth(uiAbsPartIdx)) ) { uiSubdiv = (uiLog2TrafoSize >quadtreeTULog2MinSizeInCU); } else if( uiLog2TrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { uiSubdiv = 1; } else if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { uiSubdiv = 0; } else if( uiLog2TrafoSize == quadtreeTULog2MinSizeInCU ) { uiSubdiv = 0; } else { assert( uiLog2TrafoSize > quadtreeTULog2MinSizeInCU ); m_pcEntropyDecoderIf->parseTransformSubdivFlag( uiSubdiv, 5 - uiLog2TrafoSize ); } for(Int chan=COMPONENT_Cb; chansetCbfSubParts( 0, compID, rTu.GetAbsPartIdxTU(compID), trDepthTotalAdj); } if( bFirstCbfOfCU || rTu.ProcessingAllQuadrants(compID) ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepth - 1 ) ) { m_pcEntropyDecoderIf->parseQtCbf( rTu, compID, (uiSubdiv == 0) ); } } } if( uiSubdiv ) { const UInt uiQPartNum = pcCU->getPic()->getNumPartitionsInCtu() >> ((uiDepth+1) << 1); UInt uiYUVCbf[MAX_NUM_COMPONENT] = {0,0,0}; TComTURecurse tuRecurseChild(rTu, true); do { xDecodeTransform( bCodeDQP, isChromaQpAdjCoded, tuRecurseChild, quadtreeTULog2MinSizeInCU ); UInt childTUAbsPartIdx=tuRecurseChild.GetAbsPartIdxTU(); for(UInt ch=0; chgetCbf(childTUAbsPartIdx , ComponentID(ch), uiTrDepth+1 ); } } while (tuRecurseChild.nextSection(rTu) ); for(UInt ch=0; chgetCbf( ComponentID(ch) ) + uiAbsPartIdx; const UChar flag = uiYUVCbf[ch] << uiTrDepth; for( UInt ui = 0; ui < 4 * uiQPartNum; ++ui ) { pBase[ui] |= flag; } } } else { assert( uiDepth >= pcCU->getDepth( uiAbsPartIdx ) ); pcCU->setTrIdxSubParts( uiTrDepth, uiAbsPartIdx, uiDepth ); { DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tTrIdx: abspart=" ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\tdepth=" ); DTRACE_CABAC_V( uiDepth ); DTRACE_CABAC_T( "\ttrdepth=" ); DTRACE_CABAC_V( uiTrDepth ); DTRACE_CABAC_T( "\n" ); } pcCU->setCbfSubParts ( 0, COMPONENT_Y, uiAbsPartIdx, uiDepth ); if( (!pcCU->isIntra(uiAbsPartIdx)) && uiDepth == pcCU->getDepth( uiAbsPartIdx ) && ((!bChroma) || (!pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cb, 0 ) && !pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cr, 0 )) )) { pcCU->setCbfSubParts( 1 << uiTrDepth, COMPONENT_Y, uiAbsPartIdx, uiDepth ); } else { m_pcEntropyDecoderIf->parseQtCbf( rTu, COMPONENT_Y, true ); } // transform_unit begin UInt cbf[MAX_NUM_COMPONENT]={0,0,0}; Bool validCbf = false; Bool validChromaCbf = false; const UInt uiTrIdx = rTu.GetTransformDepthRel(); for(UInt ch=0; chgetPic()->getNumberValidComponents(); ch++) { const ComponentID compID = ComponentID(ch); cbf[compID] = pcCU->getCbf( uiAbsPartIdx, compID, uiTrIdx ); if (cbf[compID] != 0) { validCbf = true; if (isChroma(compID)) { validChromaCbf = true; } } } if ( validCbf ) { // dQP: only for CTU if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { if ( bCodeDQP ) { const UInt uiAbsPartIdxCU=rTu.GetAbsPartIdxCU(); decodeQP( pcCU, uiAbsPartIdxCU); bCodeDQP = false; } } if ( pcCU->getSlice()->getUseChromaQpAdj() ) { if ( validChromaCbf && isChromaQpAdjCoded && !pcCU->getCUTransquantBypass(rTu.GetAbsPartIdxCU()) ) { decodeChromaQpAdjustment( pcCU, rTu.GetAbsPartIdxCU() ); isChromaQpAdjCoded = false; } } const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for(UInt ch=COMPONENT_Y; chgetCbf(subTUIterator.GetAbsPartIdxTU(), compID, (uiTrIdx + 1)); if (subTUCBF != 0) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("Call NxN for chan %d width=%d height=%d cbf=%d\n", compID, subTUIterator.getRect(compID).width, subTUIterator.getRect(compID).height, 1); } #endif m_pcEntropyDecoderIf->parseCoeffNxN( subTUIterator, compID ); } } while (subTUIterator.nextSection(rTu)); } else { if(isChroma(compID) && (cbf[COMPONENT_Y] != 0)) { m_pcEntropyDecoderIf->parseCrossComponentPrediction( rTu, compID ); } if(cbf[compID] != 0) { m_pcEntropyDecoderIf->parseCoeffNxN( rTu, compID ); } } } } } // transform_unit end } } Void TDecEntropy::decodeQP ( TComDataCU* pcCU, UInt uiAbsPartIdx ) { if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { m_pcEntropyDecoderIf->parseDeltaQP( pcCU, uiAbsPartIdx, pcCU->getDepth( uiAbsPartIdx ) ); } } Void TDecEntropy::decodeChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx ) { if ( pcCU->getSlice()->getUseChromaQpAdj() ) { m_pcEntropyDecoderIf->parseChromaQpAdjustment( pcCU, uiAbsPartIdx, pcCU->getDepth( uiAbsPartIdx ) ); } } //! decode coefficients Void TDecEntropy::decodeCoeff( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool& bCodeDQP, Bool& isChromaQpAdjCoded ) { if( pcCU->isIntra(uiAbsPartIdx) ) { } else { UInt uiQtRootCbf = 1; if( !( pcCU->getPartitionSize( uiAbsPartIdx) == SIZE_2Nx2N && pcCU->getMergeFlag( uiAbsPartIdx ) ) ) { m_pcEntropyDecoderIf->parseQtRootCbf( uiAbsPartIdx, uiQtRootCbf ); } if ( !uiQtRootCbf ) { static const UInt cbfZero[MAX_NUM_COMPONENT]={0,0,0}; pcCU->setCbfSubParts( cbfZero, uiAbsPartIdx, uiDepth ); pcCU->setTrIdxSubParts( 0 , uiAbsPartIdx, uiDepth ); return; } } TComTURecurse tuRecurse(pcCU, uiAbsPartIdx, uiDepth); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("..codeCoeff: uiAbsPartIdx=%d, PU format=%d, 2Nx2N=%d, NxN=%d\n", uiAbsPartIdx, pcCU->getPartitionSize(uiAbsPartIdx), SIZE_2Nx2N, SIZE_NxN); } #endif Int quadtreeTULog2MinSizeInCU = pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx); xDecodeTransform( bCodeDQP, isChromaQpAdjCoded, tuRecurse, quadtreeTULog2MinSizeInCU ); } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecEntropy.h000066400000000000000000000221321442026013100207400ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecEntropy.h \brief entropy decoder class (header) */ #ifndef __TDECENTROPY__ #define __TDECENTROPY__ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/TComSlice.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComSampleAdaptiveOffset.h" #include "TLibCommon/TComRectangle.h" #include "TDecConformance.h" class TDecSbac; class TDecCavlc; class ParameterSetManagerDecoder; class TComPrediction; //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// entropy decoder pure class class TDecEntropyIf { public: // Virtual list for SBAC/CAVLC virtual Void resetEntropy ( TComSlice* pcSlice ) = 0; virtual Void setBitstream ( TComInputBitstream* p ) = 0; virtual Void parseVPS ( TComVPS* pcVPS ) = 0; virtual Void parseSPS ( TComSPS* pcSPS ) = 0; virtual Void parsePPS ( TComPPS* pcPPS ) = 0; virtual Void parseSliceHeader ( TComSlice* pcSlice, ParameterSetManager *parameterSetManager, const Int prevTid0POC) = 0; virtual Void parseTerminatingBit ( UInt& ruilsLast ) = 0; virtual Void parseRemainingBytes( Bool noTrailingBytesExpected ) = 0; virtual Void parseMVPIdx ( Int& riMVPIdx ) = 0; public: virtual Void parseSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ) = 0; virtual Void parseMergeIndex ( TComDataCU* pcCU, UInt& ruiMergeIndex ) = 0; virtual Void parsePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parsePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseIntraDirLumaAng( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseInterDir ( TComDataCU* pcCU, UInt& ruiInterDir, UInt uiAbsPartIdx ) = 0; virtual Void parseRefFrmIdx ( TComDataCU* pcCU, Int& riRefFrmIdx, RefPicList eRefList ) = 0; virtual Void parseMvd ( TComDataCU* pcCU, UInt uiAbsPartAddr, UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ) = 0; virtual Void parseCrossComponentPrediction ( class TComTU &rTu, ComponentID compID ) = 0; virtual Void parseTransformSubdivFlag( UInt& ruiSubdivFlag, UInt uiLog2TransformBlockSize ) = 0; virtual Void parseQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) = 0; virtual Void parseQtRootCbf ( UInt uiAbsPartIdx, UInt& uiQtRootCbf ) = 0; virtual Void parseDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void parseIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth) = 0; virtual Void parseCoeffNxN( class TComTU &rTu, ComponentID compID ) = 0; virtual Void parseTransformSkipFlags ( class TComTU &rTu, ComponentID component ) = 0; virtual Void parseExplicitRdpcmMode ( TComTU &rTu, ComponentID compID ) = 0; virtual ~TDecEntropyIf() {} }; /// entropy decoder class class TDecEntropy { private: TDecEntropyIf* m_pcEntropyDecoderIf; TComPrediction* m_pcPrediction; #if MCTS_ENC_CHECK TDecConformanceCheck* m_pConformanceCheck; #endif //UInt m_uiBakAbsPartIdx; //UInt m_uiBakChromaOffset; //UInt m_bakAbsPartIdxCU; public: #if MCTS_ENC_CHECK Void init (TComPrediction* p, TDecConformanceCheck* pConformanceCheck) {m_pcPrediction = p; m_pConformanceCheck=pConformanceCheck;} #else Void init (TComPrediction* p) {m_pcPrediction = p;} #endif Void decodePUWise ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComDataCU* pcSubCU ); Void decodeInterDirPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx ); Void decodeRefFrmIdxPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ); Void decodeMvdPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ); Void decodeMVPIdxPU ( TComDataCU* pcSubCU, UInt uiPartAddr, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList ); Void setEntropyDecoder ( TDecEntropyIf* p ); Void setBitstream ( TComInputBitstream* p ) { m_pcEntropyDecoderIf->setBitstream(p); } Void resetEntropy ( TComSlice* p) { m_pcEntropyDecoderIf->resetEntropy(p); } Void decodeVPS ( TComVPS* pcVPS ) { m_pcEntropyDecoderIf->parseVPS(pcVPS); } Void decodeSPS ( TComSPS* pcSPS ) { m_pcEntropyDecoderIf->parseSPS(pcSPS); } Void decodePPS ( TComPPS* pcPPS ) { m_pcEntropyDecoderIf->parsePPS(pcPPS); } Void decodeSliceHeader ( TComSlice* pcSlice, ParameterSetManager *parameterSetManager, const Int prevTid0POC) { m_pcEntropyDecoderIf->parseSliceHeader(pcSlice, parameterSetManager, prevTid0POC); } Void decodeTerminatingBit ( UInt& ruiIsLast ) { m_pcEntropyDecoderIf->parseTerminatingBit(ruiIsLast); } Void decodeRemainingBytes( Bool noTrailingBytesExpected ) { m_pcEntropyDecoderIf->parseRemainingBytes(noTrailingBytesExpected); } TDecEntropyIf* getEntropyDecoder() { return m_pcEntropyDecoderIf; } public: Void decodeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ); Void decodeMergeIndex ( TComDataCU* pcSubCU, UInt uiPartIdx, UInt uiPartAddr, UInt uiDepth ); Void decodePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodePredInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComDataCU* pcSubCU ); Void decodeIntraDirModeLuma ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeIntraDirModeChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void decodeQP ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void decodeChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx ); private: Void xDecodeTransform ( Bool& bCodeDQP, Bool& isChromaQpAdjCoded, TComTU &rTu, const Int quadtreeTULog2MinSizeInCU ); public: Void decodeCoeff ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool& bCodeDQP, Bool& isChromaQpAdjCoded ); };// END CLASS DEFINITION TDecEntropy //! \} #endif // __TDECENTROPY__ HM-HM-18.0/source/Lib/TLibDecoder/TDecGop.cpp000066400000000000000000000221751442026013100203670ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecGop.cpp \brief GOP decoder class */ #include "TDecGop.h" #include "TDecCAVLC.h" #include "TDecSbac.h" #include "TDecBinCoder.h" #include "TDecBinCoderCABAC.h" #include "libmd5/MD5.h" #include "TLibCommon/SEI.h" #include //! \ingroup TLibDecoder //! \{ static Void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI, const BitDepths &bitDepths, UInt &numChecksumErrors); // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== TDecGop::TDecGop() : m_numberOfChecksumErrorsDetected(0) { m_dDecTime = 0; } TDecGop::~TDecGop() { } Void TDecGop::create() { } Void TDecGop::destroy() { } Void TDecGop::init( TDecEntropy* pcEntropyDecoder, TDecSbac* pcSbacDecoder, TDecBinCABAC* pcBinCABAC, TDecCavlc* pcCavlcDecoder, TDecSlice* pcSliceDecoder, TComLoopFilter* pcLoopFilter, TComSampleAdaptiveOffset* pcSAO ) { m_pcEntropyDecoder = pcEntropyDecoder; m_pcSbacDecoder = pcSbacDecoder; m_pcBinCABAC = pcBinCABAC; m_pcCavlcDecoder = pcCavlcDecoder; m_pcSliceDecoder = pcSliceDecoder; m_pcLoopFilter = pcLoopFilter; m_pcSAO = pcSAO; m_numberOfChecksumErrorsDetected = 0; } // ==================================================================================================================== // Private member functions // ==================================================================================================================== // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic* pcPic) { TComSlice* pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx()); // Table of extracted substreams. // These must be deallocated AND their internal fifos, too. TComInputBitstream **ppcSubstreams = NULL; //-- For time output for each slice clock_t iBeforeTime = clock(); m_pcSbacDecoder->init( (TDecBinIf*)m_pcBinCABAC ); m_pcEntropyDecoder->setEntropyDecoder (m_pcSbacDecoder); const UInt uiNumSubstreams = pcSlice->getNumberOfSubstreamSizes()+1; // init each couple {EntropyDecoder, Substream} ppcSubstreams = new TComInputBitstream*[uiNumSubstreams]; for ( UInt ui = 0 ; ui < uiNumSubstreams ; ui++ ) { ppcSubstreams[ui] = pcBitstream->extractSubstream(ui+1 < uiNumSubstreams ? (pcSlice->getSubstreamSize(ui)<<3) : pcBitstream->getNumBitsLeft()); } m_pcSliceDecoder->decompressSlice( ppcSubstreams, pcPic, m_pcSbacDecoder); // deallocate all created substreams, including internal buffers. for (UInt ui = 0; ui < uiNumSubstreams; ui++) { delete ppcSubstreams[ui]; } delete[] ppcSubstreams; m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; } Void TDecGop::filterPicture(TComPic* pcPic) { TComSlice* pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx()); //-- For time output for each slice clock_t iBeforeTime = clock(); // deblocking filter Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); m_pcLoopFilter->setCfg(bLFCrossTileBoundary); m_pcLoopFilter->loopFilterPic( pcPic ); if( pcSlice->getSPS()->getUseSAO() ) { m_pcSAO->reconstructBlkSAOParams(pcPic, pcPic->getPicSym()->getSAOBlkParam()); m_pcSAO->SAOProcess(pcPic); m_pcSAO->PCMLFDisableProcess(pcPic); } pcPic->compressMotion(); TChar c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B'); if (!pcSlice->isReferenced()) { c += 32; } //-- For time output for each slice printf("POC %4d TId: %1d ( %c-SLICE, QP%3d ) ", pcSlice->getPOC(), pcSlice->getTLayer(), c, pcSlice->getSliceQp() ); m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; printf ("[DT %6.3f] ", m_dDecTime ); m_dDecTime = 0; for (Int iRefList = 0; iRefList < 2; iRefList++) { printf ("[L%d ", iRefList); for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++) { printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)); } printf ("] "); } if (m_decodedPictureHashSEIEnabled) { SEIMessages pictureHashes = getSeisByType(pcPic->getSEIs(), SEI::DECODED_PICTURE_HASH ); const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL; if (pictureHashes.size() > 1) { printf ("Warning: Got multiple decoded picture hash SEI messages. Using first."); } calcAndPrintHashStatus(*(pcPic->getPicYuvRec()), hash, pcSlice->getSPS()->getBitDepths(), m_numberOfChecksumErrorsDetected); } printf("\n"); pcPic->setOutputMark(pcPic->getSlice(0)->getPicOutputFlag() ? true : false); pcPic->setReconMark(true); } /** * Calculate and print hash for pic, compare to picture_digest SEI if * present in seis. seis may be NULL. Hash is printed to stdout, in * a manner suitable for the status line. Theformat is: * [Hash_type:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,(yyy)] * Where, x..x is the hash * yyy has the following meanings: * OK - calculated hash matches the SEI message * ***ERROR*** - calculated hash does not match the SEI message * unk - no SEI message was available for comparison */ static Void calcAndPrintHashStatus(TComPicYuv& pic, const SEIDecodedPictureHash* pictureHashSEI, const BitDepths &bitDepths, UInt &numChecksumErrors) { /* calculate MD5sum for entire reconstructed picture */ TComPictureHash recon_digest; Int numChar=0; const TChar* hashType = "\0"; if (pictureHashSEI) { switch (pictureHashSEI->method) { case HASHTYPE_MD5: { hashType = "MD5"; numChar = calcMD5(pic, recon_digest, bitDepths); break; } case HASHTYPE_CRC: { hashType = "CRC"; numChar = calcCRC(pic, recon_digest, bitDepths); break; } case HASHTYPE_CHECKSUM: { hashType = "Checksum"; numChar = calcChecksum(pic, recon_digest, bitDepths); break; } default: { assert (!"unknown hash type"); break; } } } /* compare digest against received version */ const TChar* ok = "(unk)"; Bool mismatch = false; if (pictureHashSEI) { ok = "(OK)"; if (recon_digest != pictureHashSEI->m_pictureHash) { ok = "(***ERROR***)"; mismatch = true; } } printf("[%s:%s,%s] ", hashType, hashToString(recon_digest, numChar).c_str(), ok); if (mismatch) { numChecksumErrors++; printf("[rx%s:%s] ", hashType, hashToString(pictureHashSEI->m_pictureHash, numChar).c_str()); } } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecGop.h000066400000000000000000000101751442026013100200310ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecGop.h \brief GOP decoder class (header) */ #ifndef __TDECGOP__ #define __TDECGOP__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/TComList.h" #include "TLibCommon/TComPicYuv.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComLoopFilter.h" #include "TLibCommon/TComSampleAdaptiveOffset.h" #include "TDecEntropy.h" #include "TDecSlice.h" #include "TDecBinCoder.h" #include "TDecBinCoderCABAC.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// GOP decoder class class TDecGop { private: TComList m_cListPic; // Dynamic buffer // Access channel TDecEntropy* m_pcEntropyDecoder; TDecSbac* m_pcSbacDecoder; TDecBinCABAC* m_pcBinCABAC; TDecCavlc* m_pcCavlcDecoder; TDecSlice* m_pcSliceDecoder; TComLoopFilter* m_pcLoopFilter; TComSampleAdaptiveOffset* m_pcSAO; Double m_dDecTime; Int m_decodedPictureHashSEIEnabled; ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message UInt m_numberOfChecksumErrorsDetected; public: TDecGop(); virtual ~TDecGop(); Void init ( TDecEntropy* pcEntropyDecoder, TDecSbac* pcSbacDecoder, TDecBinCABAC* pcBinCABAC, TDecCavlc* pcCavlcDecoder, TDecSlice* pcSliceDecoder, TComLoopFilter* pcLoopFilter, TComSampleAdaptiveOffset* pcSAO ); Void create (); Void destroy (); Void decompressSlice(TComInputBitstream* pcBitstream, TComPic* pcPic ); Void filterPicture (TComPic* pcPic ); Void setDecodedPictureHashSEIEnabled(Int enabled) { m_decodedPictureHashSEIEnabled = enabled; } UInt getNumberOfChecksumErrorsDetected() const { return m_numberOfChecksumErrorsDetected; } }; //! \} #endif // !defined(AFX_TDECGOP_H__29440B7A_7CC0_48C7_8DD5_1A531D3CED45__INCLUDED_) HM-HM-18.0/source/Lib/TLibDecoder/TDecSbac.cpp000066400000000000000000002106101442026013100205030ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecSbac.cpp \brief Context-adaptive entropy decoder class */ #include "TDecSbac.h" #include "TLibCommon/TComTU.h" #include "TLibCommon/TComTrQuant.h" #if RExt__DECODER_DEBUG_BIT_STATISTICS #include "TLibCommon/TComCodingStatistics.h" // #define RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(a) , a #else #define RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(a) #endif //! \ingroup TLibDecoder //! \{ #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST #include "../TLibCommon/Debug.h" #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TDecSbac::TDecSbac() // new structure here : m_pcBitstream ( 0 ) , m_pcTDecBinIf ( NULL ) , m_numContextModels ( 0 ) , m_cCUSplitFlagSCModel ( 1, 1, NUM_SPLIT_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSkipFlagSCModel ( 1, 1, NUM_SKIP_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMergeFlagExtSCModel ( 1, 1, NUM_MERGE_FLAG_EXT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMergeIdxExtSCModel ( 1, 1, NUM_MERGE_IDX_EXT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUPartSizeSCModel ( 1, 1, NUM_PART_SIZE_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUPredModeSCModel ( 1, 1, NUM_PRED_MODE_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUIntraPredSCModel ( 1, 1, NUM_INTRA_PREDICT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUChromaPredSCModel ( 1, 1, NUM_CHROMA_PRED_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUDeltaQpSCModel ( 1, 1, NUM_DELTA_QP_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUInterDirSCModel ( 1, 1, NUM_INTER_DIR_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCURefPicSCModel ( 1, 1, NUM_REF_NO_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMvdSCModel ( 1, 1, NUM_MV_RES_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtCbfSCModel ( 1, NUM_QT_CBF_CTX_SETS, NUM_QT_CBF_CTX_PER_SET , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUTransSubdivFlagSCModel ( 1, 1, NUM_TRANS_SUBDIV_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtRootCbfSCModel ( 1, 1, NUM_QT_ROOT_CBF_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigCoeffGroupSCModel ( 1, 2, NUM_SIG_CG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigSCModel ( 1, 1, NUM_SIG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastX ( 1, NUM_CTX_LAST_FLAG_SETS, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastY ( 1, NUM_CTX_LAST_FLAG_SETS, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUOneSCModel ( 1, 1, NUM_ONE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUAbsSCModel ( 1, 1, NUM_ABS_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cMVPIdxSCModel ( 1, 1, NUM_MVP_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoMergeSCModel ( 1, 1, NUM_SAO_MERGE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoTypeIdxSCModel ( 1, 1, NUM_SAO_TYPE_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cTransformSkipSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_TRANSFORMSKIP_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_CUTransquantBypassFlagSCModel ( 1, 1, NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_explicitRdpcmFlagSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_EXPLICIT_RDPCM_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_explicitRdpcmDirSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_EXPLICIT_RDPCM_DIR_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCrossComponentPredictionSCModel ( 1, 1, NUM_CROSS_COMPONENT_PREDICTION_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_ChromaQpAdjFlagSCModel ( 1, 1, NUM_CHROMA_QP_ADJ_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_ChromaQpAdjIdcSCModel ( 1, 1, NUM_CHROMA_QP_ADJ_IDC_CTX , m_contextModels + m_numContextModels, m_numContextModels) { assert( m_numContextModels <= MAX_NUM_CTX_MOD ); } TDecSbac::~TDecSbac() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TDecSbac::resetEntropy(TComSlice* pSlice) { SliceType sliceType = pSlice->getSliceType(); Int qp = pSlice->getSliceQp(); if (pSlice->getPPS()->getCabacInitPresentFlag() && pSlice->getCabacInitFlag()) { switch (sliceType) { case P_SLICE: // change initialization table to B_SLICE initialization sliceType = B_SLICE; break; case B_SLICE: // change initialization table to P_SLICE initialization sliceType = P_SLICE; break; default : // should not occur assert(0); break; } } m_cCUSplitFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SPLIT_FLAG ); m_cCUSkipFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SKIP_FLAG ); m_cCUMergeFlagExtSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_MERGE_FLAG_EXT ); m_cCUMergeIdxExtSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_MERGE_IDX_EXT ); m_cCUPartSizeSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_PART_SIZE ); m_cCUPredModeSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_PRED_MODE ); m_cCUIntraPredSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_INTRA_PRED_MODE ); m_cCUChromaPredSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_CHROMA_PRED_MODE ); m_cCUInterDirSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_INTER_DIR ); m_cCUMvdSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_MVD ); m_cCURefPicSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_REF_PIC ); m_cCUDeltaQpSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_DQP ); m_cCUQtCbfSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_QT_CBF ); m_cCUQtRootCbfSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_QT_ROOT_CBF ); m_cCUSigCoeffGroupSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SIG_CG_FLAG ); m_cCUSigSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SIG_FLAG ); m_cCuCtxLastX.initBuffer ( sliceType, qp, (UChar*)INIT_LAST ); m_cCuCtxLastY.initBuffer ( sliceType, qp, (UChar*)INIT_LAST ); m_cCUOneSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_ONE_FLAG ); m_cCUAbsSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_ABS_FLAG ); m_cMVPIdxSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_MVP_IDX ); m_cSaoMergeSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SAO_MERGE_FLAG ); m_cSaoTypeIdxSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_SAO_TYPE_IDX ); m_cCUTransSubdivFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_TRANS_SUBDIV_FLAG ); m_cTransformSkipSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_TRANSFORMSKIP_FLAG ); m_CUTransquantBypassFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG ); m_explicitRdpcmFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_FLAG); m_explicitRdpcmDirSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_DIR); m_cCrossComponentPredictionSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_CROSS_COMPONENT_PREDICTION ); m_ChromaQpAdjFlagSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_FLAG ); m_ChromaQpAdjIdcSCModel.initBuffer ( sliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_IDC ); for (UInt statisticIndex = 0; statisticIndex < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS ; statisticIndex++) { m_golombRiceAdaptationStatistics[statisticIndex] = 0; } m_pcTDecBinIf->start(); } Void TDecSbac::parseTerminatingBit( UInt& ruiBit ) { m_pcTDecBinIf->decodeBinTrm( ruiBit ); if ( ruiBit == 1 ) { m_pcTDecBinIf->finish(); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::IncrementStatisticEP(STATS__TRAILING_BITS, m_pcBitstream->readOutTrailingBits(),0); #else m_pcBitstream->readOutTrailingBits(); #endif } } Void TDecSbac::parseRemainingBytes( Bool noTrailingBytesExpected ) { if (noTrailingBytesExpected) { const UInt numberOfRemainingSubstreamBytes=m_pcBitstream->getNumBitsLeft(); assert (numberOfRemainingSubstreamBytes == 0); } else { while (m_pcBitstream->getNumBitsLeft()) { UInt trailingNullByte=m_pcBitstream->readByte(); if (trailingNullByte!=0) { printf("Trailing byte should be 0, but has value %02x\n", trailingNullByte); assert(trailingNullByte==0); } } } } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecSbac::xReadUnaryMaxSymbol( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, UInt uiMaxSymbol, const class TComCodingStatisticsClassType &whichStat ) #else Void TDecSbac::xReadUnaryMaxSymbol( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, UInt uiMaxSymbol ) #endif { if (uiMaxSymbol == 0) { ruiSymbol = 0; return; } m_pcTDecBinIf->decodeBin( ruiSymbol, pcSCModel[0] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); if( ruiSymbol == 0 || uiMaxSymbol == 1 ) { return; } UInt uiSymbol = 0; UInt uiCont; do { m_pcTDecBinIf->decodeBin( uiCont, pcSCModel[ iOffset ] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); uiSymbol++; } while( uiCont && ( uiSymbol < uiMaxSymbol - 1 ) ); if( uiCont && ( uiSymbol == uiMaxSymbol - 1 ) ) { uiSymbol++; } ruiSymbol = uiSymbol; } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecSbac::xReadEpExGolomb( UInt& ruiSymbol, UInt uiCount, const class TComCodingStatisticsClassType &whichStat ) #else Void TDecSbac::xReadEpExGolomb( UInt& ruiSymbol, UInt uiCount ) #endif { UInt uiSymbol = 0; UInt uiBit = 1; while( uiBit ) { m_pcTDecBinIf->decodeBinEP( uiBit RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); uiSymbol += uiBit << uiCount++; } if ( --uiCount ) { UInt bins; m_pcTDecBinIf->decodeBinsEP( bins, uiCount RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); uiSymbol += bins; } ruiSymbol = uiSymbol; } #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecSbac::xReadUnarySymbol( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, const class TComCodingStatisticsClassType &whichStat ) #else Void TDecSbac::xReadUnarySymbol( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset ) #endif { m_pcTDecBinIf->decodeBin( ruiSymbol, pcSCModel[0] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat)); if( !ruiSymbol ) { return; } UInt uiSymbol = 0; UInt uiCont; do { m_pcTDecBinIf->decodeBin( uiCont, pcSCModel[ iOffset ] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat)); uiSymbol++; } while( uiCont ); ruiSymbol = uiSymbol; } /** Parsing of coeff_abs_level_remaing * \param rSymbol reference to coeff_abs_level_remaing * \param rParam reference to parameter * \param useLimitedPrefixLength * \param maxLog2TrDynamicRange */ #if RExt__DECODER_DEBUG_BIT_STATISTICS Void TDecSbac::xReadCoefRemainExGolomb ( UInt &rSymbol, UInt &rParam, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange, const class TComCodingStatisticsClassType &whichStat ) #else Void TDecSbac::xReadCoefRemainExGolomb ( UInt &rSymbol, UInt &rParam, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ) #endif { UInt prefix = 0; UInt codeWord = 0; if (useLimitedPrefixLength) { const UInt longestPossiblePrefix = (32 - (COEF_REMAIN_BIN_REDUCTION + maxLog2TrDynamicRange)) + COEF_REMAIN_BIN_REDUCTION; do { prefix++; m_pcTDecBinIf->decodeBinEP( codeWord RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); } while((codeWord != 0) && (prefix < longestPossiblePrefix)); } else { do { prefix++; m_pcTDecBinIf->decodeBinEP( codeWord RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat) ); } while( codeWord); } codeWord = 1 - codeWord; prefix -= codeWord; codeWord=0; if (prefix < COEF_REMAIN_BIN_REDUCTION ) { m_pcTDecBinIf->decodeBinsEP(codeWord,rParam RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat)); rSymbol = (prefix<decodeBinsEP(codeWord, (suffixLength + rParam) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat)); rSymbol = codeWord + ((((1 << prefixLength) - 1) + COEF_REMAIN_BIN_REDUCTION) << rParam); } else { m_pcTDecBinIf->decodeBinsEP(codeWord,prefix-COEF_REMAIN_BIN_REDUCTION+rParam RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(whichStat)); rSymbol = (((1<<(prefix-COEF_REMAIN_BIN_REDUCTION))+COEF_REMAIN_BIN_REDUCTION-1)<decodeBinTrm(uiSymbol); if (uiSymbol == 1) { Bool bIpcmFlag = true; const TComSPS &sps=*(pcCU->getSlice()->getSPS()); pcCU->setPartSizeSubParts ( SIZE_2Nx2N, uiAbsPartIdx, uiDepth ); pcCU->setSizeSubParts ( sps.getMaxCUWidth()>>uiDepth, sps.getMaxCUHeight()>>uiDepth, uiAbsPartIdx, uiDepth ); pcCU->setTrIdxSubParts ( 0, uiAbsPartIdx, uiDepth ); pcCU->setIPCMFlagSubParts ( bIpcmFlag, uiAbsPartIdx, uiDepth ); const UInt minCoeffSizeY = pcCU->getPic()->getMinCUWidth() * pcCU->getPic()->getMinCUHeight(); const UInt offsetY = minCoeffSizeY * uiAbsPartIdx; for (UInt ch=0; ch < pcCU->getPic()->getNumberValidComponents(); ch++) { const ComponentID compID = ComponentID(ch); const UInt offset = offsetY >> (pcCU->getPic()->getComponentScaleX(compID) + pcCU->getPic()->getComponentScaleY(compID)); Pel * pPCMSample = pcCU->getPCMSample(compID) + offset; const UInt width = pcCU->getWidth (uiAbsPartIdx) >> pcCU->getPic()->getComponentScaleX(compID); const UInt height = pcCU->getHeight(uiAbsPartIdx) >> pcCU->getPic()->getComponentScaleY(compID); const UInt sampleBits = pcCU->getSlice()->getSPS()->getPCMBitDepth(toChannelType(compID)); for (UInt y=0; yxReadPCMCode(sampleBits, sample); pPCMSample[x] = sample; } pPCMSample += width; } } m_pcTDecBinIf->start(); } } Void TDecSbac::parseCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiSymbol; m_pcTDecBinIf->decodeBin( uiSymbol, m_CUTransquantBypassFlagSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__TQ_BYPASS_FLAG) ); pcCU->setCUTransquantBypassSubParts(uiSymbol ? true : false, uiAbsPartIdx, uiDepth); } /** parse skip flag * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TDecSbac::parseSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { if( pcCU->getSlice()->isIntra() ) { return; } UInt uiSymbol = 0; UInt uiCtxSkip = pcCU->getCtxSkipFlag( uiAbsPartIdx ); m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUSkipFlagSCModel.get( 0, 0, uiCtxSkip ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SKIP_FLAG) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tSkipFlag" ); DTRACE_CABAC_T( "\tuiCtxSkip: "); DTRACE_CABAC_V( uiCtxSkip ); DTRACE_CABAC_T( "\tuiSymbol: "); DTRACE_CABAC_V( uiSymbol ); DTRACE_CABAC_T( "\n"); if( uiSymbol ) { pcCU->setSkipFlagSubParts( true, uiAbsPartIdx, uiDepth ); pcCU->setPredModeSubParts( MODE_INTER, uiAbsPartIdx, uiDepth ); pcCU->setPartSizeSubParts( SIZE_2Nx2N, uiAbsPartIdx, uiDepth ); pcCU->setSizeSubParts( pcCU->getSlice()->getSPS()->getMaxCUWidth()>>uiDepth, pcCU->getSlice()->getSPS()->getMaxCUHeight()>>uiDepth, uiAbsPartIdx, uiDepth ); pcCU->setMergeFlagSubParts( true , uiAbsPartIdx, 0, uiDepth ); } } /** parse merge flag * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \param uiPUIdx * \returns Void */ Void TDecSbac::parseMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ) { UInt uiSymbol; m_pcTDecBinIf->decodeBin( uiSymbol, *m_cCUMergeFlagExtSCModel.get( 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MERGE_FLAG) ); pcCU->setMergeFlagSubParts( uiSymbol ? true : false, uiAbsPartIdx, uiPUIdx, uiDepth ); DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tMergeFlag: " ); DTRACE_CABAC_V( uiSymbol ); DTRACE_CABAC_T( "\tAddress: " ); DTRACE_CABAC_V( pcCU->getCtuRsAddr() ); DTRACE_CABAC_T( "\tuiAbsPartIdx: " ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\n" ); } Void TDecSbac::parseMergeIndex ( TComDataCU* pcCU, UInt& ruiMergeIndex ) { UInt uiUnaryIdx = 0; UInt uiNumCand = pcCU->getSlice()->getMaxNumMergeCand(); if ( uiNumCand > 1 ) { for( ; uiUnaryIdx < uiNumCand - 1; ++uiUnaryIdx ) { UInt uiSymbol = 0; if ( uiUnaryIdx==0 ) { m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUMergeIdxExtSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MERGE_INDEX) ); } else { m_pcTDecBinIf->decodeBinEP( uiSymbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MERGE_INDEX) ); } if( uiSymbol == 0 ) { break; } } } ruiMergeIndex = uiUnaryIdx; DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseMergeIndex()" ) DTRACE_CABAC_T( "\tuiMRGIdx= " ) DTRACE_CABAC_V( ruiMergeIndex ) DTRACE_CABAC_T( "\n" ) } Void TDecSbac::parseMVPIdx ( Int& riMVPIdx ) { UInt uiSymbol; xReadUnaryMaxSymbol(uiSymbol, m_cMVPIdxSCModel.get(0), 1, AMVP_MAX_NUM_CANDS-1 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVP_IDX) ); riMVPIdx = uiSymbol; } Void TDecSbac::parseSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { if( uiDepth == pcCU->getSlice()->getSPS()->getLog2DiffMaxMinCodingBlockSize() ) { pcCU->setDepthSubParts( uiDepth, uiAbsPartIdx ); return; } #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__SPLIT_FLAG, g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth()>>uiDepth]+2); #endif UInt uiSymbol; m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUSplitFlagSCModel.get( 0, 0, pcCU->getCtxSplitFlag( uiAbsPartIdx, uiDepth ) ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tSplitFlag\n" ) pcCU->setDepthSubParts( uiDepth + uiSymbol, uiAbsPartIdx ); return; } /** parse partition size * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TDecSbac::parsePartSize( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiSymbol, uiMode = 0; PartSize eMode; const UChar cuWidth =UChar(pcCU->getSlice()->getSPS()->getMaxCUWidth()>>uiDepth); const UChar cuHeight=UChar(pcCU->getSlice()->getSPS()->getMaxCUHeight()>>uiDepth); const Int log2DiffMaxMinCodingBlockSize = pcCU->getSlice()->getSPS()->getLog2DiffMaxMinCodingBlockSize(); #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__PART_SIZE, g_aucConvertToBit[cuWidth]+2); #endif assert ( pcCU->getSlice()->getSPS()->getLog2DiffMaxMinCodingBlockSize() == log2DiffMaxMinCodingBlockSize); if ( pcCU->isIntra( uiAbsPartIdx ) ) { uiSymbol = 1; if( uiDepth == log2DiffMaxMinCodingBlockSize ) { m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUPartSizeSCModel.get( 0, 0, 0) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); } eMode = uiSymbol ? SIZE_2Nx2N : SIZE_NxN; UInt uiTrLevel = 0; UInt uiWidthInBit = g_aucConvertToBit[pcCU->getWidth(uiAbsPartIdx)]+2; UInt uiTrSizeInBit = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxTrSize()]+2; uiTrLevel = uiWidthInBit >= uiTrSizeInBit ? uiWidthInBit - uiTrSizeInBit : 0; if( eMode == SIZE_NxN ) { pcCU->setTrIdxSubParts( 1+uiTrLevel, uiAbsPartIdx, uiDepth ); } else { pcCU->setTrIdxSubParts( uiTrLevel, uiAbsPartIdx, uiDepth ); } } else { UInt uiMaxNumBits = 2; if( uiDepth == log2DiffMaxMinCodingBlockSize && !( cuWidth == 8 && cuHeight == 8 ) ) { uiMaxNumBits ++; } for ( UInt ui = 0; ui < uiMaxNumBits; ui++ ) { m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUPartSizeSCModel.get( 0, 0, ui) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if ( uiSymbol ) { break; } uiMode++; } eMode = (PartSize) uiMode; if ( pcCU->getSlice()->getSPS()->getUseAMP() && uiDepth < log2DiffMaxMinCodingBlockSize ) { if (eMode == SIZE_2NxN) { m_pcTDecBinIf->decodeBin(uiSymbol, m_cCUPartSizeSCModel.get( 0, 0, 3 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype)); if (uiSymbol == 0) { m_pcTDecBinIf->decodeBinEP(uiSymbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); eMode = (uiSymbol == 0? SIZE_2NxnU : SIZE_2NxnD); } } else if (eMode == SIZE_Nx2N) { m_pcTDecBinIf->decodeBin(uiSymbol, m_cCUPartSizeSCModel.get( 0, 0, 3 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if (uiSymbol == 0) { m_pcTDecBinIf->decodeBinEP(uiSymbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); eMode = (uiSymbol == 0? SIZE_nLx2N : SIZE_nRx2N); } } } } pcCU->setPartSizeSubParts( eMode, uiAbsPartIdx, uiDepth ); pcCU->setSizeSubParts( cuWidth, cuHeight, uiAbsPartIdx, uiDepth ); } /** parse prediction mode * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TDecSbac::parsePredMode( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { if( pcCU->getSlice()->isIntra() ) { pcCU->setPredModeSubParts( MODE_INTRA, uiAbsPartIdx, uiDepth ); return; } UInt uiSymbol; Int iPredMode = MODE_INTER; m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUPredModeSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__PRED_MODE) ); iPredMode += uiSymbol; pcCU->setPredModeSubParts( (PredMode)iPredMode, uiAbsPartIdx, uiDepth ); } Void TDecSbac::parseIntraDirLumaAng ( TComDataCU* pcCU, UInt absPartIdx, UInt depth ) { PartSize mode = pcCU->getPartitionSize( absPartIdx ); UInt partNum = mode==SIZE_NxN?4:1; UInt partOffset = ( pcCU->getPic()->getNumPartitionsInCtu() >> ( pcCU->getDepth(absPartIdx) << 1 ) ) >> 2; UInt mpmPred[4],symbol; Int j,intraPredMode; if (mode==SIZE_NxN) { depth++; } #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__INTRA_DIR_ANG, g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth()>>depth]+2, CHANNEL_TYPE_LUMA); #endif for (j=0;jdecodeBin( symbol, m_cCUIntraPredSCModel.get( 0, 0, 0) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); mpmPred[j] = symbol; } for (j=0;jgetIntraDirPredictor(absPartIdx+partOffset*j, preds, COMPONENT_Y); if (mpmPred[j]) { m_pcTDecBinIf->decodeBinEP( symbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if (symbol) { m_pcTDecBinIf->decodeBinEP( symbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); symbol++; } intraPredMode = preds[symbol]; } else { m_pcTDecBinIf->decodeBinsEP( symbol, 5 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); intraPredMode = symbol; //postponed sorting of MPMs (only in remaining branch) if (preds[0] > preds[1]) { std::swap(preds[0], preds[1]); } if (preds[0] > preds[2]) { std::swap(preds[0], preds[2]); } if (preds[1] > preds[2]) { std::swap(preds[1], preds[2]); } for ( UInt i = 0; i < NUM_MOST_PROBABLE_MODES; i++ ) { intraPredMode += ( intraPredMode >= preds[i] ); } } pcCU->setIntraDirSubParts(CHANNEL_TYPE_LUMA, (UChar)intraPredMode, absPartIdx+partOffset*j, depth ); } } Void TDecSbac::parseIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { UInt uiSymbol; #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__INTRA_DIR_ANG, g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth()>>uiDepth]+2, CHANNEL_TYPE_CHROMA); #endif m_pcTDecBinIf->decodeBin( uiSymbol, m_cCUChromaPredSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if( uiSymbol == 0 ) { uiSymbol = DM_CHROMA_IDX; } else { UInt uiIPredMode; m_pcTDecBinIf->decodeBinsEP( uiIPredMode, 2 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); UInt uiAllowedChromaDir[ NUM_CHROMA_MODE ]; pcCU->getAllowedChromaDir( uiAbsPartIdx, uiAllowedChromaDir ); uiSymbol = uiAllowedChromaDir[ uiIPredMode ]; } pcCU->setIntraDirSubParts( CHANNEL_TYPE_CHROMA, uiSymbol, uiAbsPartIdx, uiDepth ); } Void TDecSbac::parseInterDir( TComDataCU* pcCU, UInt& ruiInterDir, UInt uiAbsPartIdx ) { UInt uiSymbol; const UInt uiCtx = pcCU->getCtxInterDir( uiAbsPartIdx ); ContextModel *pCtx = m_cCUInterDirSCModel.get( 0 ); uiSymbol = 0; if (pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N || pcCU->getHeight(uiAbsPartIdx) != 8 ) { m_pcTDecBinIf->decodeBin( uiSymbol, *( pCtx + uiCtx ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__INTER_DIR) ); } if( uiSymbol ) { uiSymbol = 2; } else { m_pcTDecBinIf->decodeBin( uiSymbol, *( pCtx + 4 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__INTER_DIR) ); assert(uiSymbol == 0 || uiSymbol == 1); } uiSymbol++; ruiInterDir = uiSymbol; return; } Void TDecSbac::parseRefFrmIdx( TComDataCU* pcCU, Int& riRefFrmIdx, RefPicList eRefList ) { UInt uiSymbol; ContextModel *pCtx = m_cCURefPicSCModel.get( 0 ); m_pcTDecBinIf->decodeBin( uiSymbol, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__REF_FRM_IDX) ); if( uiSymbol ) { UInt uiRefNum = pcCU->getSlice()->getNumRefIdx( eRefList ) - 2; pCtx++; UInt ui; for( ui = 0; ui < uiRefNum; ++ui ) { if( ui == 0 ) { m_pcTDecBinIf->decodeBin( uiSymbol, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__REF_FRM_IDX) ); } else { m_pcTDecBinIf->decodeBinEP( uiSymbol RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__REF_FRM_IDX) ); } if( uiSymbol == 0 ) { break; } } uiSymbol = ui + 1; } riRefFrmIdx = uiSymbol; return; } Void TDecSbac::parseMvd( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ) { UInt uiSymbol; UInt uiHorAbs; UInt uiVerAbs; UInt uiHorSign = 0; UInt uiVerSign = 0; ContextModel *pCtx = m_cCUMvdSCModel.get( 0 ); if(pcCU->getSlice()->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_1 && pcCU->getInterDir(uiAbsPartIdx)==3) { uiHorAbs=0; uiVerAbs=0; } else { m_pcTDecBinIf->decodeBin( uiHorAbs, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD) ); m_pcTDecBinIf->decodeBin( uiVerAbs, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD) ); const Bool bHorAbsGr0 = uiHorAbs != 0; const Bool bVerAbsGr0 = uiVerAbs != 0; pCtx++; if( bHorAbsGr0 ) { m_pcTDecBinIf->decodeBin( uiSymbol, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD) ); uiHorAbs += uiSymbol; } if( bVerAbsGr0 ) { m_pcTDecBinIf->decodeBin( uiSymbol, *pCtx RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD) ); uiVerAbs += uiSymbol; } if( bHorAbsGr0 ) { if( 2 == uiHorAbs ) { xReadEpExGolomb( uiSymbol, 1 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD_EP) ); uiHorAbs += uiSymbol; } m_pcTDecBinIf->decodeBinEP( uiHorSign RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD_EP) ); } if( bVerAbsGr0 ) { if( 2 == uiVerAbs ) { xReadEpExGolomb( uiSymbol, 1 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD_EP) ); uiVerAbs += uiSymbol; } m_pcTDecBinIf->decodeBinEP( uiVerSign RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__MVD_EP) ); } } const TComMv cMv( uiHorSign ? -Int( uiHorAbs ): uiHorAbs, uiVerSign ? -Int( uiVerAbs ) : uiVerAbs ); pcCU->getCUMvField( eRefList )->setAllMvd( cMv, pcCU->getPartitionSize( uiAbsPartIdx ), uiAbsPartIdx, uiDepth, uiPartIdx ); return; } Void TDecSbac::parseCrossComponentPrediction( TComTU &rTu, ComponentID compID ) { TComDataCU *pcCU = rTu.getCU(); if( isLuma(compID) || !pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() ) { return; } const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); if (!pcCU->isIntra(uiAbsPartIdx) || (pcCU->getIntraDir( CHANNEL_TYPE_CHROMA, uiAbsPartIdx ) == DM_CHROMA_IDX)) { SChar alpha = 0; UInt symbol = 0; DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T("\tparseCrossComponentPrediction()") DTRACE_CABAC_T( "\tAddr=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( uiAbsPartIdx ) #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__CROSS_COMPONENT_PREDICTION, (g_aucConvertToBit[rTu.getRect(compID).width] + 2), compID); #endif ContextModel *pCtx = m_cCrossComponentPredictionSCModel.get(0, 0) + ((compID == COMPONENT_Cr) ? (NUM_CROSS_COMPONENT_PREDICTION_CTX >> 1) : 0); m_pcTDecBinIf->decodeBin( symbol, pCtx[0] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if(symbol != 0) { // Cross-component prediction alpha is non-zero. UInt sign = 0; m_pcTDecBinIf->decodeBin( symbol, pCtx[1] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if (symbol != 0) { // alpha is 2 (symbol=1), 4(symbol=2) or 8(symbol=3). // Read up to two more bits xReadUnaryMaxSymbol( symbol, (pCtx + 2), 1, 2 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); symbol += 1; } m_pcTDecBinIf->decodeBin( sign, pCtx[4] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); alpha = (sign != 0) ? -(1 << symbol) : (1 << symbol); } DTRACE_CABAC_T( "\tAlpha=" ) DTRACE_CABAC_V( alpha ) DTRACE_CABAC_T( "\n" ) pcCU->setCrossComponentPredictionAlphaPartRange( alpha, compID, uiAbsPartIdx, rTu.GetAbsPartIdxNumParts( compID ) ); } } Void TDecSbac::parseTransformSubdivFlag( UInt& ruiSubdivFlag, UInt uiLog2TransformBlockSize ) { m_pcTDecBinIf->decodeBin( ruiSubdivFlag, m_cCUTransSubdivFlagSCModel.get( 0, 0, uiLog2TransformBlockSize ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(TComCodingStatisticsClassType(STATS__CABAC_BITS__TRANSFORM_SUBDIV_FLAG, 5-uiLog2TransformBlockSize)) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseTransformSubdivFlag()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( ruiSubdivFlag ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiLog2TransformBlockSize ) DTRACE_CABAC_T( "\n" ) } Void TDecSbac::parseQtRootCbf( UInt uiAbsPartIdx, UInt& uiQtRootCbf ) { UInt uiSymbol; const UInt uiCtx = 0; m_pcTDecBinIf->decodeBin( uiSymbol , m_cCUQtRootCbfSCModel.get( 0, 0, uiCtx ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__QT_ROOT_CBF) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtRootCbf()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiSymbol ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( uiAbsPartIdx ) DTRACE_CABAC_T( "\n" ) uiQtRootCbf = uiSymbol; } Void TDecSbac::parseDeltaQP( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { Int qp; UInt uiDQp; Int iDQp; UInt uiSymbol; xReadUnaryMaxSymbol (uiDQp, &m_cCUDeltaQpSCModel.get( 0, 0, 0 ), 1, CU_DQP_TU_CMAX RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__DELTA_QP_EP) ); if( uiDQp >= CU_DQP_TU_CMAX) { xReadEpExGolomb( uiSymbol, CU_DQP_EG_k RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__DELTA_QP_EP)); uiDQp+=uiSymbol; } if ( uiDQp > 0 ) { UInt uiSign; Int qpBdOffsetY = pcCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA); m_pcTDecBinIf->decodeBinEP(uiSign RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__DELTA_QP_EP)); iDQp = uiDQp; if(uiSign) { iDQp = -iDQp; } qp = (((Int) pcCU->getRefQP( uiAbsPartIdx ) + iDQp + 52 + 2*qpBdOffsetY )%(52+qpBdOffsetY)) - qpBdOffsetY; } else { qp = pcCU->getRefQP(uiAbsPartIdx); } pcCU->setQPSubParts(qp, uiAbsPartIdx, uiDepth); pcCU->setCodedQP(qp); } /** parse chroma qp adjustment, converting to the internal table representation. * \returns Void */ Void TDecSbac::parseChromaQpAdjustment( TComDataCU* cu, UInt absPartIdx, UInt depth ) { UInt symbol; #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__CHROMA_QP_ADJUSTMENT, g_aucConvertToBit[cu->getSlice()->getSPS()->getMaxCUWidth()>>depth]+2, CHANNEL_TYPE_CHROMA); #endif Int chromaQpOffsetListLen = cu->getSlice()->getPPS()->getPpsRangeExtension().getChromaQpOffsetListLen(); // cu_chroma_qp_offset_flag m_pcTDecBinIf->decodeBin( symbol, m_ChromaQpAdjFlagSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if (symbol && chromaQpOffsetListLen > 1) { // cu_chroma_qp_offset_idx xReadUnaryMaxSymbol( symbol, &m_ChromaQpAdjIdcSCModel.get( 0, 0, 0 ), 0, chromaQpOffsetListLen - 1 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); symbol++; } /* NB, symbol = 0 if outer flag is not set, * 1 if outer flag is set and there is no inner flag * 1+ otherwise */ cu->setChromaQpAdjSubParts( symbol, absPartIdx, depth ); cu->setCodedChromaQpAdj(symbol); } Void TDecSbac::parseQtCbf( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) { TComDataCU* pcCU = rTu.getCU(); const UInt absPartIdx = rTu.GetAbsPartIdxTU(compID); const UInt TUDepth = rTu.GetTransformDepthRel(); const UInt uiCtx = pcCU->getCtxQtCbf( rTu, toChannelType(compID) ); const UInt contextSet = toChannelType(compID); const UInt width = rTu.getRect(compID).width; const UInt height = rTu.getRect(compID).height; const Bool canQuadSplit = (width >= (MIN_TU_SIZE * 2)) && (height >= (MIN_TU_SIZE * 2)); const UInt coveredPartIdxes = rTu.GetAbsPartIdxNumParts(compID); // Since the CBF for chroma is coded at the highest level possible, if sub-TUs are // to be coded for a 4x8 chroma TU, their CBFs must be coded at the highest 4x8 level // (i.e. where luma TUs are 8x8 rather than 4x4) // ___ ___ // | | | <- 4 x (8x8 luma + 4x8 4:2:2 chroma) // |___|___| each quadrant has its own chroma CBF // | | | _ _ _ _ // |___|___| | // <--16---> V // _ _ // |_|_| <- 4 x 4x4 luma + 1 x 4x8 4:2:2 chroma // |_|_| no chroma CBF is coded - instead the parent CBF is inherited // <-8-> if sub-TUs are present, their CBFs had to be coded at the parent level const UInt lowestTUDepth = TUDepth + ((!lowestLevel && !canQuadSplit) ? 1 : 0); //unsplittable TUs inherit their parent's CBF UInt lowestTUCBF = 0; if ((width != height) && (lowestLevel || !canQuadSplit)) //if sub-TUs are present { const UInt subTUDepth = lowestTUDepth + 1; const UInt partIdxesPerSubTU = rTu.GetAbsPartIdxNumParts(compID) >> 1; UInt combinedSubTUCBF = 0; for (UInt subTU = 0; subTU < 2; subTU++) { UInt uiCbf = MAX_UINT; m_pcTDecBinIf->decodeBin(uiCbf, m_cCUQtCbfSCModel.get(0, contextSet, uiCtx) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(TComCodingStatisticsClassType(STATS__CABAC_BITS__QT_CBF, g_aucConvertToBit[rTu.getRect(compID).width]+2, compID))); const UInt subTUAbsPartIdx = absPartIdx + (subTU * partIdxesPerSubTU); pcCU->setCbfPartRange((uiCbf << subTUDepth), compID, subTUAbsPartIdx, partIdxesPerSubTU); combinedSubTUCBF |= uiCbf; DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtCbf()" ) DTRACE_CABAC_T( "\tsub-TU=" ) DTRACE_CABAC_V( subTU ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiCbf ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( subTUAbsPartIdx ) DTRACE_CABAC_T( "\n" ) } //propagate the sub-TU CBF up to the lowest TU level if (combinedSubTUCBF != 0) { pcCU->bitwiseOrCbfPartRange((combinedSubTUCBF << lowestTUDepth), compID, absPartIdx, coveredPartIdxes); lowestTUCBF = combinedSubTUCBF; } } else { UInt uiCbf = MAX_UINT; m_pcTDecBinIf->decodeBin(uiCbf, m_cCUQtCbfSCModel.get(0, contextSet, uiCtx) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(TComCodingStatisticsClassType(STATS__CABAC_BITS__QT_CBF, g_aucConvertToBit[rTu.getRect(compID).width]+2, compID))); pcCU->setCbfSubParts((uiCbf << lowestTUDepth), compID, absPartIdx, rTu.GetTransformDepthTotalAdj(compID)); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtCbf()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiCbf ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( rTu.GetAbsPartIdxTU(compID) ) DTRACE_CABAC_T( "\n" ) lowestTUCBF = uiCbf; } //propagate the lowest level CBF up to the current level if (lowestTUCBF != 0) { for (UInt depth = TUDepth; depth < lowestTUDepth; depth++) { pcCU->bitwiseOrCbfPartRange((lowestTUCBF << depth), compID, absPartIdx, coveredPartIdxes); } } } Void TDecSbac::parseTransformSkipFlags (TComTU &rTu, ComponentID component) { TComDataCU* pcCU=rTu.getCU(); UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(component); if (pcCU->getCUTransquantBypass(uiAbsPartIdx)) { return; } if (!TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(component), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize())) { return; } UInt useTransformSkip; m_pcTDecBinIf->decodeBin( useTransformSkip , m_cTransformSkipSCModel.get( 0, toChannelType(component), 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(TComCodingStatisticsClassType(STATS__CABAC_BITS__TRANSFORM_SKIP_FLAGS, component)) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T("\tparseTransformSkip()"); DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( useTransformSkip ) DTRACE_CABAC_T( "\tAddr=" ) DTRACE_CABAC_V( pcCU->getCtuRsAddr() ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( component ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( rTu.GetAbsPartIdxTU() ) DTRACE_CABAC_T( "\n" ) pcCU->setTransformSkipPartRange( useTransformSkip, component, uiAbsPartIdx, rTu.GetAbsPartIdxNumParts(component)); } /** Parse (X,Y) position of the last significant coefficient * \param uiPosLastX reference to X component of last coefficient * \param uiPosLastY reference to Y component of last coefficient * \param width Block width * \param height Block height * \param component chroma compinent ID * \param uiScanIdx scan type (zig-zag, hor, ver) * * This method decodes the X and Y component within a block of the last significant coefficient. */ Void TDecSbac::parseLastSignificantXY( UInt& uiPosLastX, UInt& uiPosLastY, Int width, Int height, ComponentID component, UInt uiScanIdx ) { UInt uiLast; ContextModel *pCtxX = m_cCuCtxLastX.get( 0, toChannelType(component) ); ContextModel *pCtxY = m_cCuCtxLastY.get( 0, toChannelType(component) ); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatisticsClassType ctype(STATS__CABAC_BITS__LAST_SIG_X_Y, g_aucConvertToBit[width]+2, component); #endif if ( uiScanIdx == SCAN_VER ) { swap( width, height ); } Int blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY; getLastSignificantContextParameters(component, width, height, blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY); //------------------ // posX for( uiPosLastX = 0; uiPosLastX < g_uiGroupIdx[ width - 1 ]; uiPosLastX++ ) { m_pcTDecBinIf->decodeBin( uiLast, *( pCtxX + blkSizeOffsetX + (uiPosLastX >>shiftX) ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if( !uiLast ) { break; } } // posY for( uiPosLastY = 0; uiPosLastY < g_uiGroupIdx[ height - 1 ]; uiPosLastY++ ) { m_pcTDecBinIf->decodeBin( uiLast, *( pCtxY + blkSizeOffsetY + (uiPosLastY >>shiftY)) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); if( !uiLast ) { break; } } // EP-coded part if ( uiPosLastX > 3 ) { UInt uiTemp = 0; UInt uiCount = ( uiPosLastX - 2 ) >> 1; for ( Int i = uiCount - 1; i >= 0; i-- ) { m_pcTDecBinIf->decodeBinEP( uiLast RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); uiTemp += uiLast << i; } uiPosLastX = g_uiMinInGroup[ uiPosLastX ] + uiTemp; } if ( uiPosLastY > 3 ) { UInt uiTemp = 0; UInt uiCount = ( uiPosLastY - 2 ) >> 1; for ( Int i = uiCount - 1; i >= 0; i-- ) { m_pcTDecBinIf->decodeBinEP( uiLast RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype) ); uiTemp += uiLast << i; } uiPosLastY = g_uiMinInGroup[ uiPosLastY ] + uiTemp; } if( uiScanIdx == SCAN_VER ) { swap( uiPosLastX, uiPosLastY ); } } Void TDecSbac::parseCoeffNxN( TComTU &rTu, ComponentID compID ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(compID); const TComRectangle &rRect=rTu.getRect(compID); const UInt uiWidth=rRect.width; const UInt uiHeight=rRect.height; TCoeff* pcCoef=(pcCU->getCoeff(compID)+rTu.getCoefficientOffset(compID)); const TComSPS &sps=*(pcCU->getSlice()->getSPS()); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseCoeffNxN()\teType=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\twidth=" ) DTRACE_CABAC_V( uiWidth ) DTRACE_CABAC_T( "\theight=" ) DTRACE_CABAC_V( uiHeight ) DTRACE_CABAC_T( "\tdepth=" ) // DTRACE_CABAC_V( rTu.GetTransformDepthTotalAdj(compID) ) DTRACE_CABAC_V( rTu.GetTransformDepthTotal() ) DTRACE_CABAC_T( "\tabspartidx=" ) // DTRACE_CABAC_V( uiAbsPartIdx ) DTRACE_CABAC_V( rTu.GetAbsPartIdxTU(compID) ) DTRACE_CABAC_T( "\ttoCU-X=" ) DTRACE_CABAC_V( pcCU->getCUPelX() ) DTRACE_CABAC_T( "\ttoCU-Y=" ) DTRACE_CABAC_V( pcCU->getCUPelY() ) DTRACE_CABAC_T( "\tCU-addr=" ) DTRACE_CABAC_V( pcCU->getCtuRsAddr() ) DTRACE_CABAC_T( "\tinCU-X=" ) // DTRACE_CABAC_V( g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ] ) DTRACE_CABAC_V( g_auiRasterToPelX[ g_auiZscanToRaster[rTu.GetAbsPartIdxTU(compID)] ] ) DTRACE_CABAC_T( "\tinCU-Y=" ) // DTRACE_CABAC_V( g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ] ) DTRACE_CABAC_V( g_auiRasterToPelY[ g_auiZscanToRaster[rTu.GetAbsPartIdxTU(compID)] ] ) DTRACE_CABAC_T( "\tpredmode=" ) DTRACE_CABAC_V( pcCU->getPredictionMode( uiAbsPartIdx ) ) DTRACE_CABAC_T( "\n" ) //-------------------------------------------------------------------------------------------------- if( uiWidth > sps.getMaxTrSize() ) { std::cerr << "ERROR: parseCoeffNxN was passed a TU with dimensions larger than the maximum allowed size" << std::endl; assert(false); exit(1); } //-------------------------------------------------------------------------------------------------- //set parameters const ChannelType chType = toChannelType(compID); const UInt uiLog2BlockWidth = g_aucConvertToBit[ uiWidth ] + 2; const UInt uiLog2BlockHeight = g_aucConvertToBit[ uiHeight ] + 2; const UInt uiMaxNumCoeff = uiWidth * uiHeight; const UInt uiMaxNumCoeffM1 = uiMaxNumCoeff - 1; const ChannelType channelType = toChannelType(compID); const Bool extendedPrecision = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag(); const Bool alignCABACBeforeBypass = sps.getSpsRangeExtension().getCabacBypassAlignmentEnabledFlag(); const Int maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(channelType); #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatisticsClassType ctype_group(STATS__CABAC_BITS__SIG_COEFF_GROUP_FLAG, uiLog2BlockWidth, compID); TComCodingStatisticsClassType ctype_map(STATS__CABAC_BITS__SIG_COEFF_MAP_FLAG, uiLog2BlockWidth, compID); TComCodingStatisticsClassType ctype_gt1(STATS__CABAC_BITS__GT1_FLAG, uiLog2BlockWidth, compID); TComCodingStatisticsClassType ctype_gt2(STATS__CABAC_BITS__GT2_FLAG, uiLog2BlockWidth, compID); #endif Bool beValid; if (pcCU->getCUTransquantBypass(uiAbsPartIdx)) { beValid = false; if((!pcCU->isIntra(uiAbsPartIdx)) && pcCU->isRDPCMEnabled(uiAbsPartIdx)) { parseExplicitRdpcmMode(rTu, compID); } } else { beValid = pcCU->getSlice()->getPPS()->getSignDataHidingEnabledFlag(); } UInt absSum = 0; //-------------------------------------------------------------------------------------------------- if(pcCU->getSlice()->getPPS()->getUseTransformSkip()) { parseTransformSkipFlags(rTu, compID); // This TU has coefficients and is transform skipped. Check whether is inter coded and if yes decode the explicit RDPCM mode if(pcCU->getTransformSkip(uiAbsPartIdx, compID) && (!pcCU->isIntra(uiAbsPartIdx)) && pcCU->isRDPCMEnabled(uiAbsPartIdx) ) { parseExplicitRdpcmMode(rTu, compID); if(pcCU->getExplicitRdpcmMode(compID, uiAbsPartIdx) != RDPCM_OFF) { // Sign data hiding is avoided for horizontal and vertical RDPCM modes beValid = false; } } } Int uiIntraMode = -1; const Bool bIsLuma = isLuma(compID); Int isIntra = pcCU->isIntra(uiAbsPartIdx) ? 1 : 0; if ( isIntra && pcCU->isRDPCMEnabled(uiAbsPartIdx) ) { const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize())); uiIntraMode = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx ); uiIntraMode = (uiIntraMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, rTu.GetChromaFormat(), partsPerMinCU)) : uiIntraMode; uiIntraMode = ((rTu.GetChromaFormat() == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiIntraMode] : uiIntraMode; Bool transformSkip = pcCU->getTransformSkip( uiAbsPartIdx,compID); Bool rdpcm_lossy = ( transformSkip /*&& isIntra*/ && ( (uiIntraMode == HOR_IDX) || (uiIntraMode == VER_IDX) ) ); if ( rdpcm_lossy ) { beValid = false; } } //-------------------------------------------------------------------------------------------------- const Bool bUseGolombRiceParameterAdaptation = sps.getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag(); UInt ¤tGolombRiceStatistic = m_golombRiceAdaptationStatistics[rTu.getGolombRiceStatisticsIndex(compID)]; //select scans TUEntropyCodingParameters codingParameters; getTUEntropyCodingParameters(codingParameters, rTu, compID); //===== decode last significant ===== UInt uiPosLastX, uiPosLastY; parseLastSignificantXY( uiPosLastX, uiPosLastY, uiWidth, uiHeight, compID, codingParameters.scanType ); UInt uiBlkPosLast = uiPosLastX + (uiPosLastY<> MLS_CG_SIZE; UInt c1 = 1; UInt uiGoRiceParam = 0; UInt uiSigCoeffGroupFlag[ MLS_GRP_NUM ]; memset( uiSigCoeffGroupFlag, 0, sizeof(UInt) * MLS_GRP_NUM ); Int iScanPosSig = (Int) uiScanPosLast; for( Int iSubSet = iLastScanSet; iSubSet >= 0; iSubSet-- ) { Int iSubPos = iSubSet << MLS_CG_SIZE; uiGoRiceParam = currentGolombRiceStatistic / RExt__GOLOMB_RICE_INCREMENT_DIVISOR; Bool updateGolombRiceStatistics = bUseGolombRiceParameterAdaptation; //leave the statistics at 0 when not using the adaptation system Int numNonZero = 0; Int lastNZPosInCG = -1; Int firstNZPosInCG = 1 << MLS_CG_SIZE; Bool escapeDataPresentInGroup = false; Int pos[1 << MLS_CG_SIZE]; if( iScanPosSig == (Int) uiScanPosLast ) { lastNZPosInCG = iScanPosSig; firstNZPosInCG = iScanPosSig; iScanPosSig--; pos[ numNonZero ] = uiBlkPosLast; numNonZero = 1; } // decode significant_coeffgroup_flag Int iCGBlkPos = codingParameters.scanCG[ iSubSet ]; Int iCGPosY = iCGBlkPos / codingParameters.widthInGroups; Int iCGPosX = iCGBlkPos - (iCGPosY * codingParameters.widthInGroups); if( iSubSet == iLastScanSet || iSubSet == 0) { uiSigCoeffGroupFlag[ iCGBlkPos ] = 1; } else { UInt uiSigCoeffGroup; UInt uiCtxSig = TComTrQuant::getSigCoeffGroupCtxInc( uiSigCoeffGroupFlag, iCGPosX, iCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups ); m_pcTDecBinIf->decodeBin( uiSigCoeffGroup, baseCoeffGroupCtx[ uiCtxSig ] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_group) ); uiSigCoeffGroupFlag[ iCGBlkPos ] = uiSigCoeffGroup; } // decode significant_coeff_flag const Int patternSigCtx = TComTrQuant::calcPatternSigCtx(uiSigCoeffGroupFlag, iCGPosX, iCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups); UInt uiBlkPos, uiSig, uiCtxSig; for( ; iScanPosSig >= iSubPos; iScanPosSig-- ) { uiBlkPos = codingParameters.scan[ iScanPosSig ]; uiSig = 0; if( uiSigCoeffGroupFlag[ iCGBlkPos ] ) { if( iScanPosSig > iSubPos || iSubSet == 0 || numNonZero ) { uiCtxSig = TComTrQuant::getSigCtxInc( patternSigCtx, codingParameters, iScanPosSig, uiLog2BlockWidth, uiLog2BlockHeight, chType ); m_pcTDecBinIf->decodeBin( uiSig, baseCtx[ uiCtxSig ] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_map) ); } else { uiSig = 1; } } pcCoef[ uiBlkPos ] = uiSig; if( uiSig ) { pos[ numNonZero ] = uiBlkPos; numNonZero ++; if( lastNZPosInCG == -1 ) { lastNZPosInCG = iScanPosSig; } firstNZPosInCG = iScanPosSig; } } if( numNonZero > 0 ) { Bool signHidden = ( lastNZPosInCG - firstNZPosInCG >= SBH_THRESHOLD ); absSum = 0; const UInt uiCtxSet = getContextSetIndex(compID, iSubSet, (c1 == 0)); c1 = 1; UInt uiBin; ContextModel *baseCtxMod = m_cCUOneSCModel.get( 0, 0 ) + (NUM_ONE_FLAG_CTX_PER_SET * uiCtxSet); Int absCoeff[1 << MLS_CG_SIZE]; for ( Int i = 0; i < numNonZero; i++) { absCoeff[i] = 1; } Int numC1Flag = min(numNonZero, C1FLAG_NUMBER); Int firstC2FlagIdx = -1; for( Int idx = 0; idx < numC1Flag; idx++ ) { m_pcTDecBinIf->decodeBin( uiBin, baseCtxMod[c1] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_gt1) ); if( uiBin == 1 ) { c1 = 0; if (firstC2FlagIdx == -1) { firstC2FlagIdx = idx; } else //if a greater-than-one has been encountered already this group { escapeDataPresentInGroup = true; } } else if( (c1 < 3) && (c1 > 0) ) { c1++; } absCoeff[ idx ] = uiBin + 1; } if (c1 == 0) { baseCtxMod = m_cCUAbsSCModel.get( 0, 0 ) + (NUM_ABS_FLAG_CTX_PER_SET * uiCtxSet); if ( firstC2FlagIdx != -1) { m_pcTDecBinIf->decodeBin( uiBin, baseCtxMod[0] RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_gt2) ); absCoeff[ firstC2FlagIdx ] = uiBin + 2; if (uiBin != 0) { escapeDataPresentInGroup = true; } } } escapeDataPresentInGroup = escapeDataPresentInGroup || (numNonZero > C1FLAG_NUMBER); const Bool alignGroup = escapeDataPresentInGroup && alignCABACBeforeBypass; #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatisticsClassType ctype_signs((alignGroup ? STATS__CABAC_BITS__ALIGNED_SIGN_BIT : STATS__CABAC_BITS__SIGN_BIT ), uiLog2BlockWidth, compID); TComCodingStatisticsClassType ctype_escs ((alignGroup ? STATS__CABAC_BITS__ALIGNED_ESCAPE_BITS : STATS__CABAC_BITS__ESCAPE_BITS), uiLog2BlockWidth, compID); #endif if (alignGroup) { m_pcTDecBinIf->align(); } UInt coeffSigns; if ( signHidden && beValid ) { m_pcTDecBinIf->decodeBinsEP( coeffSigns, numNonZero-1 RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_signs) ); coeffSigns <<= 32 - (numNonZero-1); } else { m_pcTDecBinIf->decodeBinsEP( coeffSigns, numNonZero RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_signs) ); coeffSigns <<= 32 - numNonZero; } Int iFirstCoeff2 = 1; if (escapeDataPresentInGroup) { for( Int idx = 0; idx < numNonZero; idx++ ) { UInt baseLevel = (idx < C1FLAG_NUMBER)? (2 + iFirstCoeff2) : 1; if( absCoeff[ idx ] == baseLevel) { UInt uiLevel; xReadCoefRemainExGolomb( uiLevel, uiGoRiceParam, extendedPrecision, maxLog2TrDynamicRange RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype_escs) ); absCoeff[ idx ] = uiLevel + baseLevel; if (absCoeff[idx] > (3 << uiGoRiceParam)) { uiGoRiceParam = bUseGolombRiceParameterAdaptation ? (uiGoRiceParam + 1) : (std::min((uiGoRiceParam + 1), 4)); } if (updateGolombRiceStatistics) { const UInt initialGolombRiceParameter = currentGolombRiceStatistic / RExt__GOLOMB_RICE_INCREMENT_DIVISOR; if (uiLevel >= (3 << initialGolombRiceParameter)) { currentGolombRiceStatistic++; } else if (((uiLevel * 2) < (1 << initialGolombRiceParameter)) && (currentGolombRiceStatistic > 0)) { currentGolombRiceStatistic--; } updateGolombRiceStatistics = false; } } if(absCoeff[ idx ] >= 2) { iFirstCoeff2 = 0; } } } for( Int idx = 0; idx < numNonZero; idx++ ) { Int blkPos = pos[ idx ]; // Signs applied later. pcCoef[ blkPos ] = absCoeff[ idx ]; absSum += absCoeff[ idx ]; if ( idx == numNonZero-1 && signHidden && beValid ) { // Infer sign of 1st element. if (absSum&0x1) { pcCoef[ blkPos ] = -pcCoef[ blkPos ]; } } else { Int sign = static_cast( coeffSigns ) >> 31; pcCoef[ blkPos ] = ( pcCoef[ blkPos ] ^ sign ) - sign; coeffSigns <<= 1; } } } } #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST printSBACCoeffData(uiPosLastX, uiPosLastY, uiWidth, uiHeight, compID, uiAbsPartIdx, codingParameters.scanType, pcCoef); #endif return; } Void TDecSbac::parseSaoMaxUvlc ( UInt& val, UInt maxSymbol ) { if (maxSymbol == 0) { val = 0; return; } UInt code; Int i; m_pcTDecBinIf->decodeBinEP( code RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); if ( code == 0 ) { val = 0; return; } i=1; while (1) { m_pcTDecBinIf->decodeBinEP( code RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); if ( code == 0 ) { break; } i++; if (i == maxSymbol) { break; } } val = i; } Void TDecSbac::parseSaoUflc (UInt uiLength, UInt& riVal) { m_pcTDecBinIf->decodeBinsEP ( riVal, uiLength RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); } Void TDecSbac::parseSaoMerge (UInt& ruiVal) { UInt uiCode; m_pcTDecBinIf->decodeBin( uiCode, m_cSaoMergeSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); ruiVal = (Int)uiCode; } Void TDecSbac::parseSaoTypeIdx (UInt& ruiVal) { UInt uiCode; m_pcTDecBinIf->decodeBin( uiCode, m_cSaoTypeIdxSCModel.get( 0, 0, 0 ) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); if (uiCode == 0) { ruiVal = 0; } else { m_pcTDecBinIf->decodeBinEP( uiCode RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); if (uiCode == 0) { ruiVal = 1; } else { ruiVal = 2; } } } Void TDecSbac::parseSaoSign(UInt& val) { m_pcTDecBinIf->decodeBinEP ( val RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(STATS__CABAC_BITS__SAO) ); } Void TDecSbac::parseSAOBlkParam (SAOBlkParam& saoBlkParam , Bool* sliceEnabled , Bool leftMergeAvail , Bool aboveMergeAvail , const BitDepths &bitDepths ) { UInt uiSymbol; Bool isLeftMerge = false; Bool isAboveMerge= false; if(leftMergeAvail) { parseSaoMerge(uiSymbol); //sao_merge_left_flag isLeftMerge = (uiSymbol?true:false); } if( aboveMergeAvail && !isLeftMerge) { parseSaoMerge(uiSymbol); //sao_merge_up_flag isAboveMerge = (uiSymbol?true:false); } if(isLeftMerge || isAboveMerge) //merge mode { for (UInt componentIndex = 0; componentIndex < MAX_NUM_COMPONENT; componentIndex++) { saoBlkParam[componentIndex].modeIdc = (sliceEnabled[componentIndex]) ? SAO_MODE_MERGE : SAO_MODE_OFF; saoBlkParam[componentIndex].typeIdc = (isLeftMerge)?SAO_MERGE_LEFT:SAO_MERGE_ABOVE; } } else //new or off mode { for(Int compId=COMPONENT_Y; compId < MAX_NUM_COMPONENT; compId++) { const ComponentID compIdx=ComponentID(compId); const ComponentID firstCompOfChType = getFirstComponentOfChannel(toChannelType(compIdx)); SAOOffset& ctbParam = saoBlkParam[compIdx]; #if O0043_BEST_EFFORT_DECODING const Int bitDepthOrig = bitDepths.stream[toChannelType(compIdx)]; const Int forceBitDepthAdjust = bitDepthOrig - bitDepths.recon[toChannelType(compIdx)]; #else const Int bitDepthOrig = bitDepths.recon[toChannelType(compIdx)]; #endif const Int maxOffsetQVal=TComSampleAdaptiveOffset::getMaxOffsetQVal(bitDepthOrig); if(!sliceEnabled[compIdx]) { //off ctbParam.modeIdc = SAO_MODE_OFF; continue; } //type if(compIdx == firstCompOfChType) { parseSaoTypeIdx(uiSymbol); //sao_type_idx_luma or sao_type_idx_chroma assert(uiSymbol ==0 || uiSymbol ==1 || uiSymbol ==2); if(uiSymbol ==0) //OFF { ctbParam.modeIdc = SAO_MODE_OFF; } else if(uiSymbol == 1) //BO { ctbParam.modeIdc = SAO_MODE_NEW; ctbParam.typeIdc = SAO_TYPE_START_BO; } else //2, EO { ctbParam.modeIdc = SAO_MODE_NEW; ctbParam.typeIdc = SAO_TYPE_START_EO; } } else //Cr, follow Cb SAO type { ctbParam.modeIdc = saoBlkParam[COMPONENT_Cb].modeIdc; ctbParam.typeIdc = saoBlkParam[COMPONENT_Cb].typeIdc; } if(ctbParam.modeIdc == SAO_MODE_NEW) { Int offset[4]; for(Int i=0; i< 4; i++) { parseSaoMaxUvlc(uiSymbol, maxOffsetQVal ); //sao_offset_abs offset[i] = (Int)uiSymbol; } if(ctbParam.typeIdc == SAO_TYPE_START_BO) { for(Int i=0; i< 4; i++) { if(offset[i] != 0) { parseSaoSign(uiSymbol); //sao_offset_sign if(uiSymbol) { #if O0043_BEST_EFFORT_DECODING offset[i] >>= forceBitDepthAdjust; #endif offset[i] = -offset[i]; } } } parseSaoUflc(NUM_SAO_BO_CLASSES_LOG2, uiSymbol ); //sao_band_position ctbParam.typeAuxInfo = uiSymbol; for(Int i=0; i<4; i++) { ctbParam.offset[(ctbParam.typeAuxInfo+i)%MAX_NUM_SAO_CLASSES] = offset[i]; } } else //EO { ctbParam.typeAuxInfo = 0; if(firstCompOfChType == compIdx) { parseSaoUflc(NUM_SAO_EO_TYPES_LOG2, uiSymbol ); //sao_eo_class_luma or sao_eo_class_chroma ctbParam.typeIdc += uiSymbol; } else { ctbParam.typeIdc = saoBlkParam[firstCompOfChType].typeIdc; } ctbParam.offset[SAO_CLASS_EO_FULL_VALLEY] = offset[0]; ctbParam.offset[SAO_CLASS_EO_HALF_VALLEY] = offset[1]; ctbParam.offset[SAO_CLASS_EO_PLAIN ] = 0; ctbParam.offset[SAO_CLASS_EO_HALF_PEAK ] = -offset[2]; ctbParam.offset[SAO_CLASS_EO_FULL_PEAK ] = -offset[3]; } } } } } /** - Initialize our contexts from the nominated source. . \param pSrc Contexts to be copied. */ Void TDecSbac::xCopyContextsFrom( const TDecSbac* pSrc ) { memcpy(m_contextModels, pSrc->m_contextModels, m_numContextModels*sizeof(m_contextModels[0])); memcpy(m_golombRiceAdaptationStatistics, pSrc->m_golombRiceAdaptationStatistics, (sizeof(UInt) * RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS)); } Void TDecSbac::xCopyFrom( const TDecSbac* pSrc ) { m_pcTDecBinIf->copyState( pSrc->m_pcTDecBinIf ); xCopyContextsFrom( pSrc ); } Void TDecSbac::load ( const TDecSbac* pSrc ) { xCopyFrom(pSrc); } Void TDecSbac::loadContexts ( const TDecSbac* pSrc ) { xCopyContextsFrom(pSrc); } /** Performs CABAC decoding of the explicit RDPCM mode * \param rTu current TU data structure * \param compID component identifier */ Void TDecSbac::parseExplicitRdpcmMode( TComTU &rTu, ComponentID compID ) { TComDataCU* cu = rTu.getCU(); const UInt absPartIdx=rTu.GetAbsPartIdxTU(compID); const TComRectangle &rect = rTu.getRect(compID); const UInt tuHeight = g_aucConvertToBit[rect.height]; const UInt tuWidth = g_aucConvertToBit[rect.width]; UInt code = 0; assert(tuHeight == tuWidth); #if RExt__DECODER_DEBUG_BIT_STATISTICS const TComCodingStatisticsClassType ctype(STATS__EXPLICIT_RDPCM_BITS, g_aucConvertToBit[cu->getSlice()->getSPS()->getMaxCUWidth()>>rTu.GetTransformDepthTotal()]+2); #endif m_pcTDecBinIf->decodeBin(code, m_explicitRdpcmFlagSCModel.get (0, toChannelType(compID), 0) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype)); if(code == 0) { cu->setExplicitRdpcmModePartRange( RDPCM_OFF, compID, absPartIdx, rTu.GetAbsPartIdxNumParts(compID)); } else { m_pcTDecBinIf->decodeBin(code, m_explicitRdpcmDirSCModel.get (0, toChannelType(compID), 0) RExt__DECODER_DEBUG_BIT_STATISTICS_PASS_OPT_ARG(ctype)); if(code == 0) { cu->setExplicitRdpcmModePartRange( RDPCM_HOR, compID, absPartIdx, rTu.GetAbsPartIdxNumParts(compID)); } else { cu->setExplicitRdpcmModePartRange( RDPCM_VER, compID, absPartIdx, rTu.GetAbsPartIdxNumParts(compID)); } } } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecSbac.h000066400000000000000000000214211442026013100201500ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecSbac.h \brief SBAC decoder class (header) */ #ifndef __TDECSBAC__ #define __TDECSBAC__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TDecEntropy.h" #include "TDecBinCoder.h" #include "TLibCommon/ContextTables.h" #include "TLibCommon/ContextModel.h" #include "TLibCommon/ContextModel3DBuffer.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class SEImessages; /// SBAC decoder class class TDecSbac : public TDecEntropyIf { public: TDecSbac(); virtual ~TDecSbac(); Void init ( TDecBinIf* p ) { m_pcTDecBinIf = p; } Void uninit ( ) { m_pcTDecBinIf = 0; } Void load ( const TDecSbac* pSrc ); Void loadContexts ( const TDecSbac* pSrc ); Void xCopyFrom ( const TDecSbac* pSrc ); Void xCopyContextsFrom ( const TDecSbac* pSrc ); Void resetEntropy (TComSlice* pSlice ); Void setBitstream ( TComInputBitstream* p ) { m_pcBitstream = p; m_pcTDecBinIf->init( p ); } Void parseVPS ( TComVPS* /*pcVPS*/ ) {} Void parseSPS ( TComSPS* /*pcSPS*/ ) {} Void parsePPS ( TComPPS* /*pcPPS*/ ) {} Void parseSliceHeader ( TComSlice* /*pcSlice*/, ParameterSetManager* /*parameterSetManager*/, const Int /*prevTid0POC*/) {} Void parseTerminatingBit ( UInt& ruiBit ); Void parseRemainingBytes ( Bool noTrailingBytesExpected); Void parseMVPIdx ( Int& riMVPIdx ); Void parseSaoMaxUvlc ( UInt& val, UInt maxSymbol ); Void parseSaoMerge ( UInt& ruiVal ); Void parseSaoTypeIdx ( UInt& ruiVal ); Void parseSaoUflc ( UInt uiLength, UInt& ruiVal ); Void parseSAOBlkParam (SAOBlkParam& saoBlkParam, Bool* sliceEnabled, Bool leftMergeAvail, Bool aboveMergeAvail, const BitDepths &bitDepths); Void parseSaoSign (UInt& val); private: #if RExt__DECODER_DEBUG_BIT_STATISTICS Void xReadUnarySymbol ( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, const class TComCodingStatisticsClassType &whichStat ); Void xReadUnaryMaxSymbol ( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, UInt uiMaxSymbol, const class TComCodingStatisticsClassType &whichStat ); Void xReadEpExGolomb ( UInt& ruiSymbol, UInt uiCount, const class TComCodingStatisticsClassType &whichStat ); Void xReadCoefRemainExGolomb ( UInt &rSymbol, UInt &rParam, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange, const class TComCodingStatisticsClassType &whichStat ); #else Void xReadUnarySymbol ( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset ); Void xReadUnaryMaxSymbol ( UInt& ruiSymbol, ContextModel* pcSCModel, Int iOffset, UInt uiMaxSymbol ); Void xReadEpExGolomb ( UInt& ruiSymbol, UInt uiCount ); Void xReadCoefRemainExGolomb ( UInt &rSymbol, UInt &rParam, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ); #endif private: TComInputBitstream* m_pcBitstream; TDecBinIf* m_pcTDecBinIf; public: Void parseSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ); Void parseMergeIndex ( TComDataCU* pcCU, UInt& ruiMergeIndex ); Void parsePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parsePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseIntraDirLumaAng( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseInterDir ( TComDataCU* pcCU, UInt& ruiInterDir, UInt uiAbsPartIdx ); Void parseRefFrmIdx ( TComDataCU* pcCU, Int& riRefFrmIdx, RefPicList eRefList ); Void parseMvd ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ); Void parseCrossComponentPrediction ( class TComTU &rTu, ComponentID compID ); Void parseTransformSubdivFlag( UInt& ruiSubdivFlag, UInt uiLog2TransformBlockSize ); Void parseQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ); Void parseQtRootCbf ( UInt uiAbsPartIdx, UInt& uiQtRootCbf ); Void parseDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void parseChromaQpAdjustment( TComDataCU* cu, UInt absPartIdx, UInt depth ); Void parseIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth); Void parseLastSignificantXY( UInt& uiPosLastX, UInt& uiPosLastY, Int width, Int height, ComponentID component, UInt uiScanIdx ); Void parseCoeffNxN ( class TComTU &rTu, ComponentID compID ); Void parseTransformSkipFlags ( class TComTU &rTu, ComponentID component ); Void parseScalingList ( TComScalingList* /*scalingList*/ ) {} Void parseExplicitRdpcmMode( TComTU &rTu, ComponentID compID ); private: ContextModel m_contextModels[MAX_NUM_CTX_MOD]; Int m_numContextModels; ContextModel3DBuffer m_cCUSplitFlagSCModel; ContextModel3DBuffer m_cCUSkipFlagSCModel; ContextModel3DBuffer m_cCUMergeFlagExtSCModel; ContextModel3DBuffer m_cCUMergeIdxExtSCModel; ContextModel3DBuffer m_cCUPartSizeSCModel; ContextModel3DBuffer m_cCUPredModeSCModel; ContextModel3DBuffer m_cCUIntraPredSCModel; ContextModel3DBuffer m_cCUChromaPredSCModel; ContextModel3DBuffer m_cCUDeltaQpSCModel; ContextModel3DBuffer m_cCUInterDirSCModel; ContextModel3DBuffer m_cCURefPicSCModel; ContextModel3DBuffer m_cCUMvdSCModel; ContextModel3DBuffer m_cCUQtCbfSCModel; ContextModel3DBuffer m_cCUTransSubdivFlagSCModel; ContextModel3DBuffer m_cCUQtRootCbfSCModel; ContextModel3DBuffer m_cCUSigCoeffGroupSCModel; ContextModel3DBuffer m_cCUSigSCModel; ContextModel3DBuffer m_cCuCtxLastX; ContextModel3DBuffer m_cCuCtxLastY; ContextModel3DBuffer m_cCUOneSCModel; ContextModel3DBuffer m_cCUAbsSCModel; ContextModel3DBuffer m_cMVPIdxSCModel; ContextModel3DBuffer m_cSaoMergeSCModel; ContextModel3DBuffer m_cSaoTypeIdxSCModel; ContextModel3DBuffer m_cTransformSkipSCModel; ContextModel3DBuffer m_CUTransquantBypassFlagSCModel; ContextModel3DBuffer m_explicitRdpcmFlagSCModel; ContextModel3DBuffer m_explicitRdpcmDirSCModel; ContextModel3DBuffer m_cCrossComponentPredictionSCModel; ContextModel3DBuffer m_ChromaQpAdjFlagSCModel; ContextModel3DBuffer m_ChromaQpAdjIdcSCModel; UInt m_golombRiceAdaptationStatistics[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS]; }; //! \} #endif // !defined(AFX_TDECSBAC_H__CFCAAA19_8110_47F4_9A16_810C4B5499D5__INCLUDED_) HM-HM-18.0/source/Lib/TLibDecoder/TDecSlice.cpp000066400000000000000000000237421442026013100207020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecSlice.cpp \brief slice decoder class */ #include "TDecSlice.h" #include "TDecConformance.h" //! \ingroup TLibDecoder //! \{ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TDecSlice::TDecSlice() { } TDecSlice::~TDecSlice() { } Void TDecSlice::create() { } Void TDecSlice::destroy() { } Void TDecSlice::init(TDecEntropy* pcEntropyDecoder, TDecCu* pcCuDecoder, TDecConformanceCheck *pDecConformanceCheck) { m_pcEntropyDecoder = pcEntropyDecoder; m_pcCuDecoder = pcCuDecoder; m_pDecConformanceCheck = pDecConformanceCheck; } Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic* pcPic, TDecSbac* pcSbacDecoder) { TComSlice* pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx()); const Int startCtuTsAddr = pcSlice->getSliceSegmentCurStartCtuTsAddr(); const Int startCtuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTsAddr); const UInt numCtusInFrame = pcPic->getNumberOfCtusInFrame(); const UInt frameWidthInCtus = pcPic->getPicSym()->getFrameWidthInCtus(); const Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag(); const Bool wavefrontsEnabled = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag(); m_pcEntropyDecoder->setEntropyDecoder ( pcSbacDecoder ); m_pcEntropyDecoder->setBitstream ( ppcSubstreams[0] ); m_pcEntropyDecoder->resetEntropy (pcSlice); // decoder doesn't need prediction & residual frame buffer pcPic->setPicYuvPred( 0 ); pcPic->setPicYuvResi( 0 ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( pcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif // The first CTU of the slice is the first coded substream, but the global substream number, as calculated by getSubstreamForCtuAddr may be higher. // This calculates the common offset for all substreams in this slice. const UInt subStreamOffset=pcPic->getSubstreamForCtuAddr(startCtuRsAddr, true, pcSlice); if (depSliceSegmentsEnabled) { // modify initial contexts with previous slice segment if this is a dependent slice. const UInt startTileIdx=pcPic->getPicSym()->getTileIdxMap(startCtuRsAddr); const TComTile *pCurrentTile=pcPic->getPicSym()->getTComTile(startTileIdx); const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr(); if( pcSlice->getDependentSliceSegmentFlag() && startCtuRsAddr != firstCtuRsAddrOfTile) { if ( pCurrentTile->getTileWidthInCtus() >= 2 || !wavefrontsEnabled) { pcSbacDecoder->loadContexts(&m_lastSliceSegmentEndContextState); } } } // for every CTU in the slice segment... Bool isLastCtuOfSliceSegment = false; for( UInt ctuTsAddr = startCtuTsAddr; !isLastCtuOfSliceSegment && ctuTsAddr < numCtusInFrame; ctuTsAddr++) { const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr); const TComTile ¤tTile = *(pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr))); const UInt firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr(); const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus; const UInt tileYPosInCtus = firstCtuRsAddrOfTile / frameWidthInCtus; const UInt ctuXPosInCtus = ctuRsAddr % frameWidthInCtus; const UInt ctuYPosInCtus = ctuRsAddr / frameWidthInCtus; const UInt uiSubStrm=pcPic->getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice)-subStreamOffset; TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); pCtu->initCtu( pcPic, ctuRsAddr ); m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiSubStrm] ); // set up CABAC contexts' state for this CTU if (ctuRsAddr == firstCtuRsAddrOfTile) { if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyDecoder->resetEntropy(pcSlice); } } else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled) { // Synchronize cabac probabilities with upper-right CTU if it's available and at the start of a line. if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyDecoder->resetEntropy(pcSlice); } TComDataCU *pCtuUp = pCtu->getCtuAbove(); if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus) ) { TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 ); if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) ) { // Top-right is available, so use it. pcSbacDecoder->loadContexts( &m_entropyCodingSyncContextState ); } } } #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif #if DECODER_PARTIAL_CONFORMANCE_CHECK != 0 const UInt numRemainingBitsPriorToCtu=ppcSubstreams[uiSubStrm]->getNumBitsLeft(); #endif if ( pcSlice->getSPS()->getUseSAO() ) { SAOBlkParam& saoblkParam = (pcPic->getPicSym()->getSAOBlkParam())[ctuRsAddr]; Bool bIsSAOSliceEnabled = false; Bool sliceEnabled[MAX_NUM_COMPONENT]; for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++) { ComponentID compId=ComponentID(comp); sliceEnabled[compId] = pcSlice->getSaoEnabledFlag(toChannelType(compId)) && (comp < pcPic->getNumberValidComponents()); if (sliceEnabled[compId]) { bIsSAOSliceEnabled=true; } saoblkParam[compId].modeIdc = SAO_MODE_OFF; } if (bIsSAOSliceEnabled) { Bool leftMergeAvail = false; Bool aboveMergeAvail= false; //merge left condition Int rx = (ctuRsAddr % frameWidthInCtus); if(rx > 0) { leftMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-1); } //merge up condition Int ry = (ctuRsAddr / frameWidthInCtus); if(ry > 0) { aboveMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-frameWidthInCtus); } pcSbacDecoder->parseSAOBlkParam( saoblkParam, sliceEnabled, leftMergeAvail, aboveMergeAvail, pcSlice->getSPS()->getBitDepths()); } } m_pcCuDecoder->decodeCtu ( pCtu, isLastCtuOfSliceSegment ); #if DECODER_PARTIAL_CONFORMANCE_CHECK != 0 const UInt numRemainingBitsPostCtu=ppcSubstreams[uiSubStrm]->getNumBitsLeft(); // NOTE: Does not account for changes in buffered bits in CABAC decoder, although it's probably good enough. if (TDecConformanceCheck::doChecking() && m_pDecConformanceCheck) { m_pDecConformanceCheck->checkCtuDecoding(numRemainingBitsPriorToCtu-numRemainingBitsPostCtu); } #endif m_pcCuDecoder->decompressCtu ( pCtu ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif //Store probabilities of second CTU in line into buffer if ( ctuXPosInCtus == tileXPosInCtus+1 && wavefrontsEnabled) { m_entropyCodingSyncContextState.loadContexts( pcSbacDecoder ); } if (isLastCtuOfSliceSegment) { #if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES pcSbacDecoder->parseRemainingBytes(false); #endif if(!pcSlice->getDependentSliceSegmentFlag()) { pcSlice->setSliceCurEndCtuTsAddr( ctuTsAddr+1 ); } pcSlice->setSliceSegmentCurEndCtuTsAddr( ctuTsAddr+1 ); } else if ( ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus() && ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled) ) { // The sub-stream/stream should be terminated after this CTU. // (end of slice-segment, end of tile, end of wavefront-CTU-row) UInt binVal; pcSbacDecoder->parseTerminatingBit( binVal ); assert( binVal ); #if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES pcSbacDecoder->parseRemainingBytes(true); #endif } } assert(isLastCtuOfSliceSegment == true); if( depSliceSegmentsEnabled ) { m_lastSliceSegmentEndContextState.loadContexts( pcSbacDecoder );//ctx end of dep.slice } } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecSlice.h000066400000000000000000000065321442026013100203450ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecSlice.h \brief slice decoder class (header) */ #ifndef __TDECSLICE__ #define __TDECSLICE__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/TComPic.h" #include "TDecEntropy.h" #include "TDecCu.h" #include "TDecSbac.h" #include "TDecBinCoderCABAC.h" //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class TDecConformanceCheck; /// slice decoder class class TDecSlice { private: // access channel TDecEntropy* m_pcEntropyDecoder; TDecCu* m_pcCuDecoder; TDecConformanceCheck *m_pDecConformanceCheck; TDecSbac m_lastSliceSegmentEndContextState; ///< context storage for state at the end of the previous slice-segment (used for dependent slices only). TDecSbac m_entropyCodingSyncContextState; ///< context storate for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row public: TDecSlice(); virtual ~TDecSlice(); Void init ( TDecEntropy* pcEntropyDecoder, TDecCu* pcMbDecoder, TDecConformanceCheck *pDecConformanceCheck ); Void create (); Void destroy (); Void decompressSlice ( TComInputBitstream** ppcSubstreams, TComPic* pcPic, TDecSbac* pcSbacDecoder ); }; //! \} #endif HM-HM-18.0/source/Lib/TLibDecoder/TDecTop.cpp000066400000000000000000001047411442026013100204040ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecTop.cpp \brief decoder class */ #include "NALread.h" #include "TDecTop.h" #include "TDecConformance.h" //! \ingroup TLibDecoder //! \{ TDecTop::TDecTop() : m_iMaxRefPicNum(0) , m_associatedIRAPType(NAL_UNIT_INVALID) , m_pocCRA(0) , m_pocRandomAccess(MAX_INT) , m_cListPic() , m_parameterSetManager() , m_apcSlicePilot(NULL) , m_SEIs() , m_cPrediction() , m_cTrQuant() , m_cGopDecoder() , m_cSliceDecoder() , m_cCuDecoder() , m_cEntropyDecoder() , m_cCavlcDecoder() , m_cSbacDecoder() , m_cBinCABAC() , m_seiReader() , m_cLoopFilter() , m_cSAO() , m_pcPic(NULL) , m_prevPOC(MAX_INT) , m_prevTid0POC(0) , m_bFirstSliceInPicture(true) #if JVET_X0048_X0103_FILM_GRAIN , m_bFirstPictureInSequence(true) , m_grainCharacteristic() , m_grainBuf() #endif , m_bFirstSliceInSequence(true) , m_prevSliceSkipped(false) , m_skippedPOC(0) , m_bFirstSliceInBitstream(true) , m_lastPOCNoOutputPriorPics(-1) , m_isNoOutputPriorPics(false) , m_craNoRaslOutputFlag(false) #if O0043_BEST_EFFORT_DECODING , m_forceDecodeBitDepth(8) #endif , m_pDecodedSEIOutputStream(NULL) , m_warningMessageSkipPicture(false) #if MCTS_ENC_CHECK , m_tmctsCheckEnabled(false) #endif , m_prefixSEINALUs() { #if ENC_DEC_TRACE if (g_hTrace == NULL) { g_hTrace = fopen( "TraceDec.txt", "wb" ); } g_bJustDoIt = g_bEncDecTraceDisable; g_nSymbolCounter = 0; #endif } TDecTop::~TDecTop() { #if ENC_DEC_TRACE if (g_hTrace != stdout) { fclose( g_hTrace ); } #endif while (!m_prefixSEINALUs.empty()) { delete m_prefixSEINALUs.front(); m_prefixSEINALUs.pop_front(); } } Void TDecTop::create() { m_cGopDecoder.create(); m_apcSlicePilot = new TComSlice; m_uiSliceIdx = 0; } Void TDecTop::destroy() { m_cGopDecoder.destroy(); delete m_apcSlicePilot; m_apcSlicePilot = NULL; m_cSliceDecoder.destroy(); } Void TDecTop::init() { // initialize ROM initROM(); m_cGopDecoder.init( &m_cEntropyDecoder, &m_cSbacDecoder, &m_cBinCABAC, &m_cCavlcDecoder, &m_cSliceDecoder, &m_cLoopFilter, &m_cSAO); m_cSliceDecoder.init( &m_cEntropyDecoder, &m_cCuDecoder, &m_conformanceCheck ); #if MCTS_ENC_CHECK m_cEntropyDecoder.init(&m_cPrediction, &m_conformanceCheck ); #else m_cEntropyDecoder.init(&m_cPrediction); #endif } Void TDecTop::deletePicBuffer ( ) { TComList::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for (Int i = 0; i < iSize; i++ ) { TComPic* pcPic = *(iterPic++); pcPic->destroy(); delete pcPic; pcPic = NULL; } m_cSAO.destroy(); m_cLoopFilter. destroy(); // destroy ROM destroyROM(); } Void TDecTop::xGetNewPicBuffer ( const TComSPS &sps, const TComPPS &pps, TComPic*& rpcPic, const UInt temporalLayer ) { m_iMaxRefPicNum = sps.getMaxDecPicBuffering(temporalLayer); // m_uiMaxDecPicBuffering has the space for the picture currently being decoded if (m_cListPic.size() < (UInt)m_iMaxRefPicNum) { rpcPic = new TComPic(); #if REDUCED_ENCODER_MEMORY rpcPic->create ( sps, pps, false, true #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , false #endif ); #else rpcPic->create ( sps, pps, true #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , false #endif ); #endif m_cListPic.pushBack( rpcPic ); return; } Bool bBufferIsAvailable = false; TComList::iterator iterPic = m_cListPic.begin(); while (iterPic != m_cListPic.end()) { rpcPic = *(iterPic++); if ( rpcPic->getReconMark() == false && rpcPic->getOutputMark() == false) { rpcPic->setOutputMark(false); bBufferIsAvailable = true; break; } if ( rpcPic->getSlice( 0 )->isReferenced() == false && rpcPic->getOutputMark() == false) { rpcPic->setOutputMark(false); rpcPic->setReconMark( false ); rpcPic->getPicYuvRec()->setBorderExtension( false ); bBufferIsAvailable = true; break; } } if ( !bBufferIsAvailable ) { //There is no room for this picture, either because of faulty encoder or dropped NAL. Extend the buffer. m_iMaxRefPicNum++; rpcPic = new TComPic(); m_cListPic.pushBack( rpcPic ); } rpcPic->destroy(); #if REDUCED_ENCODER_MEMORY rpcPic->create ( sps, pps, false, true #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , false #endif ); #else rpcPic->create ( sps, pps, true #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , false #endif ); #endif } Void TDecTop::executeLoopFilters(Int& poc, TComList*& rpcListPic) { if (!m_pcPic) { /* nothing to deblock */ return; } TComPic* pcPic = m_pcPic; // Execute Deblock + Cleanup m_cGopDecoder.filterPicture(pcPic); TComSlice::sortPicList( m_cListPic ); // sorting for application output poc = pcPic->getSlice(m_uiSliceIdx-1)->getPOC(); rpcListPic = &m_cListPic; m_cCuDecoder.destroy(); m_bFirstSliceInPicture = true; return; } Void TDecTop::checkNoOutputPriorPics (TComList* pcListPic) { if (!pcListPic || !m_isNoOutputPriorPics) { return; } TComList::iterator iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { TComPic* pcPicTmp = *(iterPic++); if (m_lastPOCNoOutputPriorPics != pcPicTmp->getPOC()) { pcPicTmp->setOutputMark(false); } } } Void TDecTop::xCreateLostPicture(Int iLostPoc) { printf("\ninserting lost poc : %d\n",iLostPoc); TComPic *cFillPic; xGetNewPicBuffer(*(m_parameterSetManager.getFirstSPS()), *(m_parameterSetManager.getFirstPPS()), cFillPic, 0); cFillPic->getSlice(0)->initSlice(); TComList::iterator iterPic = m_cListPic.begin(); Int closestPoc = 1000000; while ( iterPic != m_cListPic.end()) { TComPic * rpcPic = *(iterPic++); if(abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc)getPicSym()->getSlice(0)->getPOC() -iLostPoc)!=0&&rpcPic->getPicSym()->getSlice(0)->getPOC()!=m_apcSlicePilot->getPOC()) { closestPoc=abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc); } } iterPic = m_cListPic.begin(); while ( iterPic != m_cListPic.end()) { TComPic *rpcPic = *(iterPic++); if(abs(rpcPic->getPicSym()->getSlice(0)->getPOC() -iLostPoc)==closestPoc&&rpcPic->getPicSym()->getSlice(0)->getPOC()!=m_apcSlicePilot->getPOC()) { printf("copying picture %d to %d (%d)\n",rpcPic->getPicSym()->getSlice(0)->getPOC() ,iLostPoc,m_apcSlicePilot->getPOC()); rpcPic->getPicYuvRec()->copyToPic(cFillPic->getPicYuvRec()); break; } } cFillPic->setCurrSliceIdx(0); for(Int ctuRsAddr=0; ctuRsAddrgetNumberOfCtusInFrame(); ctuRsAddr++) { cFillPic->getCtu(ctuRsAddr)->initCtu(cFillPic, ctuRsAddr); } cFillPic->getSlice(0)->setReferenced(true); cFillPic->getSlice(0)->setPOC(iLostPoc); xUpdatePreviousTid0POC(cFillPic->getSlice(0)); cFillPic->setReconMark(true); cFillPic->setOutputMark(true); if(m_pocRandomAccess == MAX_INT) { m_pocRandomAccess = iLostPoc; } } #if MCTS_EXTRACTION Void TDecTop::xActivateParameterSets(Bool bSkipCabacAndReconstruction) #else Void TDecTop::xActivateParameterSets() #endif { if (m_bFirstSliceInPicture) { const TComPPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); // this is a temporary PPS object. Do not store this value assert (pps != 0); const TComSPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); // this is a temporary SPS object. Do not store this value assert (sps != 0); m_parameterSetManager.clearSPSChangedFlag(sps->getSPSId()); m_parameterSetManager.clearPPSChangedFlag(pps->getPPSId()); if (false == m_parameterSetManager.activatePPS(m_apcSlicePilot->getPPSId(),m_apcSlicePilot->isIRAP())) { printf ("Parameter set activation failed!"); assert (0); } xParsePrefixSEImessages(); #if MCTS_ENC_CHECK xAnalysePrefixSEImessages(); #endif #if RExt__HIGH_BIT_DEPTH_SUPPORT==0 if (sps->getSpsRangeExtension().getExtendedPrecisionProcessingFlag() || sps->getBitDepth(CHANNEL_TYPE_LUMA)>12 || sps->getBitDepth(CHANNEL_TYPE_CHROMA)>12 ) { printf("High bit depth support must be enabled at compile-time in order to decode this bitstream\n"); assert (0); exit(1); } #endif // NOTE: globals were set up here originally. You can now use: // g_uiMaxCUDepth = sps->getMaxTotalCUDepth(); // g_uiAddCUDepth = sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize() // Get a new picture buffer. This will also set up m_pcPic, and therefore give us a SPS and PPS pointer that we can use. xGetNewPicBuffer (*(sps), *(pps), m_pcPic, m_apcSlicePilot->getTLayer()); m_apcSlicePilot->applyReferencePictureSet(m_cListPic, m_apcSlicePilot->getRPS()); #if JVET_X0048_X0103_FILM_GRAIN // Initialization of film grain synthesizer m_pcPic->createGrainSynthesizer(m_bFirstPictureInSequence, &m_grainCharacteristic, &m_grainBuf, sps); m_bFirstPictureInSequence = false; #endif // make the slice-pilot a real slice, and set up the slice-pilot for the next slice assert(m_pcPic->getNumAllocatedSlice() == (m_uiSliceIdx + 1)); m_apcSlicePilot = m_pcPic->getPicSym()->swapSliceObject(m_apcSlicePilot, m_uiSliceIdx); // we now have a real slice: TComSlice *pSlice = m_pcPic->getSlice(m_uiSliceIdx); // Update the PPS and SPS pointers with the ones of the picture. pps=pSlice->getPPS(); sps=pSlice->getSPS(); // Initialise the various objects for the new set of settings m_cSAO.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), sps->getChromaFormatIdc(), sps->getMaxCUWidth(), sps->getMaxCUHeight(), sps->getMaxTotalCUDepth(), pps->getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_LUMA), pps->getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA) ); m_cLoopFilter.create( sps->getMaxTotalCUDepth() ); m_cPrediction.initTempBuff(sps->getChromaFormatIdc()); Bool isField = false; Bool isTopField = false; if(!m_SEIs.empty()) { // Check if any new Picture Timing SEI has arrived SEIMessages pictureTimingSEIs = getSeisByType(m_SEIs, SEI::PICTURE_TIMING); if (pictureTimingSEIs.size()>0) { SEIPictureTiming* pictureTiming = (SEIPictureTiming*) *(pictureTimingSEIs.begin()); isField = (pictureTiming->m_picStruct == 1) || (pictureTiming->m_picStruct == 2) || (pictureTiming->m_picStruct == 9) || (pictureTiming->m_picStruct == 10) || (pictureTiming->m_picStruct == 11) || (pictureTiming->m_picStruct == 12); isTopField = (pictureTiming->m_picStruct == 1) || (pictureTiming->m_picStruct == 9) || (pictureTiming->m_picStruct == 11); } } //Set Field/Frame coding mode m_pcPic->setField(isField); m_pcPic->setTopField(isTopField); // transfer any SEI messages that have been received to the picture m_pcPic->setSEIs(m_SEIs); m_SEIs.clear(); #if MCTS_EXTRACTION if (!bSkipCabacAndReconstruction) { #endif // Recursive structure m_cCuDecoder.create ( sps->getMaxTotalCUDepth(), sps->getMaxCUWidth(), sps->getMaxCUHeight(), sps->getChromaFormatIdc() ); #if MCTS_ENC_CHECK m_cCuDecoder.init ( &m_cEntropyDecoder, &m_cTrQuant, &m_cPrediction, &m_conformanceCheck ); #else m_cCuDecoder.init(&m_cEntropyDecoder, &m_cTrQuant, &m_cPrediction); #endif m_cTrQuant.init ( sps->getMaxTrSize() ); m_cSliceDecoder.create(); } #if MCTS_EXTRACTION } #endif else { // make the slice-pilot a real slice, and set up the slice-pilot for the next slice m_pcPic->allocateNewSlice(); assert(m_pcPic->getNumAllocatedSlice() == (m_uiSliceIdx + 1)); m_apcSlicePilot = m_pcPic->getPicSym()->swapSliceObject(m_apcSlicePilot, m_uiSliceIdx); TComSlice *pSlice = m_pcPic->getSlice(m_uiSliceIdx); // we now have a real slice. const TComSPS *sps = pSlice->getSPS(); const TComPPS *pps = pSlice->getPPS(); // check that the current active PPS has not changed... if (m_parameterSetManager.getSPSChangedFlag(sps->getSPSId()) ) { printf("Error - a new SPS has been decoded while processing a picture\n"); exit(1); } if (m_parameterSetManager.getPPSChangedFlag(pps->getPPSId()) ) { printf("Error - a new PPS has been decoded while processing a picture\n"); exit(1); } xParsePrefixSEImessages(); #if MCTS_ENC_CHECK xAnalysePrefixSEImessages(); #endif // Check if any new SEI has arrived if(!m_SEIs.empty()) { // Currently only decoding Unit SEI message occurring between VCL NALUs copied SEIMessages &picSEI = m_pcPic->getSEIs(); SEIMessages decodingUnitInfos = extractSeisByType (m_SEIs, SEI::DECODING_UNIT_INFO); picSEI.insert(picSEI.end(), decodingUnitInfos.begin(), decodingUnitInfos.end()); deleteSEIs(m_SEIs); } } } Void TDecTop::xParsePrefixSEIsForUnknownVCLNal() { while (!m_prefixSEINALUs.empty()) { // do nothing? printf("Discarding Prefix SEI associated with unknown VCL NAL unit.\n"); delete m_prefixSEINALUs.front(); } // TODO: discard following suffix SEIs as well? } Void TDecTop::xParsePrefixSEImessages() { while (!m_prefixSEINALUs.empty()) { InputNALUnit &nalu=*m_prefixSEINALUs.front(); m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_pDecodedSEIOutputStream ); delete m_prefixSEINALUs.front(); m_prefixSEINALUs.pop_front(); } } #if MCTS_ENC_CHECK Void TDecTop::xAnalysePrefixSEImessages() { if (m_tmctsCheckEnabled) { SEIMessages mctsSEIs = getSeisByType(m_SEIs, SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS); for (SEIMessages::iterator it = mctsSEIs.begin(); it != mctsSEIs.end(); it++) { SEITempMotionConstrainedTileSets *mcts = (SEITempMotionConstrainedTileSets*)(*it); if (!mcts->m_each_tile_one_tile_set_flag) { printf("cannot (yet) check Temporal constrained MCTS if each_tile_one_tile_set_flag is not enabled\n"); exit(1); } else { printf("MCTS check enabled!\n"); m_conformanceCheck.enableTMctsCheck(true); } } } } #endif #if MCTS_EXTRACTION Bool TDecTop::xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay, Bool bSkipCabacAndReconstruction) #else Bool TDecTop::xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay) #endif { m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice // it is not associated with picture, sps or pps structures. if (m_bFirstSliceInPicture) { m_uiSliceIdx = 0; } else { m_apcSlicePilot->copySliceInfo( m_pcPic->getPicSym()->getSlice(m_uiSliceIdx-1) ); } m_apcSlicePilot->setSliceIdx(m_uiSliceIdx); m_apcSlicePilot->setNalUnitType(nalu.m_nalUnitType); Bool nonReferenceFlag = (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_STSA_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N); m_apcSlicePilot->setTemporalLayerNonReferenceFlag(nonReferenceFlag); m_apcSlicePilot->setReferenced(true); // Putting this as true ensures that picture is referenced the first time it is in an RPS m_apcSlicePilot->setTLayerInfo(nalu.m_temporalId); #if ENC_DEC_TRACE const UInt64 originalSymbolCount = g_nSymbolCounter; #endif m_cEntropyDecoder.decodeSliceHeader (m_apcSlicePilot, &m_parameterSetManager, m_prevTid0POC); // set POC for dependent slices in skipped pictures if(m_apcSlicePilot->getDependentSliceSegmentFlag() && m_prevSliceSkipped) { m_apcSlicePilot->setPOC(m_skippedPOC); } xUpdatePreviousTid0POC(m_apcSlicePilot); m_apcSlicePilot->setAssociatedIRAPPOC(m_pocCRA); m_apcSlicePilot->setAssociatedIRAPType(m_associatedIRAPType); //For inference of NoOutputOfPriorPicsFlag if (m_apcSlicePilot->getRapPicFlag()) { if ((m_apcSlicePilot->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && m_apcSlicePilot->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsBlaFlag())) { m_apcSlicePilot->setNoRaslOutputFlag(true); } //the inference for NoOutputPriorPicsFlag if (!m_bFirstSliceInBitstream && m_apcSlicePilot->getRapPicFlag() && m_apcSlicePilot->getNoRaslOutputFlag()) { if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) { m_apcSlicePilot->setNoOutputPriorPicsFlag(true); } } else { m_apcSlicePilot->setNoOutputPriorPicsFlag(false); } if(m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) { m_craNoRaslOutputFlag = m_apcSlicePilot->getNoRaslOutputFlag(); } } if (m_apcSlicePilot->getRapPicFlag() && m_apcSlicePilot->getNoOutputPriorPicsFlag()) { m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); m_isNoOutputPriorPics = true; } else { m_isNoOutputPriorPics = false; } //For inference of PicOutputFlag if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R) { if ( m_craNoRaslOutputFlag ) { m_apcSlicePilot->setPicOutputFlag(false); } } if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_craNoRaslOutputFlag) //Reset POC MSB when CRA has NoRaslOutputFlag equal to 1 { TComPPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); assert (pps != 0); TComSPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); assert (sps != 0); Int iMaxPOClsb = 1 << sps->getBitsForPOC(); m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & (iMaxPOClsb - 1) ); xUpdatePreviousTid0POC(m_apcSlicePilot); } // Skip pictures due to random access if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay)) { m_prevSliceSkipped = true; m_skippedPOC = m_apcSlicePilot->getPOC(); return false; } // Skip TFD pictures associated with BLA/BLANT pictures if (isSkipPictureForBLA(iPOCLastDisplay)) { m_prevSliceSkipped = true; m_skippedPOC = m_apcSlicePilot->getPOC(); return false; } // clear previous slice skipped flag m_prevSliceSkipped = false; //we should only get a different poc for a new picture (with CTU address==0) if (!m_apcSlicePilot->getDependentSliceSegmentFlag() && m_apcSlicePilot->getPOC()!=m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() != 0)) { printf ("Warning, the first slice of a picture might have been lost!\n"); } // exit when a new picture is found if (!m_apcSlicePilot->getDependentSliceSegmentFlag() && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture) ) { if (m_prevPOC >= m_pocRandomAccess) { m_prevPOC = m_apcSlicePilot->getPOC(); #if ENC_DEC_TRACE //rewind the trace counter since we didn't actually decode the slice g_nSymbolCounter = originalSymbolCount; #endif return true; } m_prevPOC = m_apcSlicePilot->getPOC(); } //detect lost reference picture and insert copy of earlier frame. { Int lostPoc; while((lostPoc=m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPS(), true, m_pocRandomAccess)) > 0) { xCreateLostPicture(lostPoc-1); } } if (!m_apcSlicePilot->getDependentSliceSegmentFlag()) { m_prevPOC = m_apcSlicePilot->getPOC(); } // actual decoding starts here #if MCTS_EXTRACTION xActivateParameterSets(bSkipCabacAndReconstruction); #else xActivateParameterSets(); #endif TComSlice* pcSlice = m_pcPic->getPicSym()->getSlice(m_uiSliceIdx); if (TDecConformanceCheck::doChecking()) { m_conformanceCheck.checkSliceActivation(*pcSlice, nalu, *m_pcPic, m_bFirstSliceInBitstream, m_bFirstSliceInSequence, m_bFirstSliceInPicture); } m_bFirstSliceInSequence = false; m_bFirstSliceInBitstream = false; // When decoding the slice header, the stored start and end addresses were actually RS addresses, not TS addresses. // Now, having set up the maps, convert them to the correct form. pcSlice->setSliceSegmentCurStartCtuTsAddr( m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()) ); pcSlice->setSliceSegmentCurEndCtuTsAddr( m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurEndCtuTsAddr()) ); if(!pcSlice->getDependentSliceSegmentFlag()) { pcSlice->setSliceCurStartCtuTsAddr(m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceCurStartCtuTsAddr())); pcSlice->setSliceCurEndCtuTsAddr(m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceCurEndCtuTsAddr())); } m_pcPic->setTLayer(nalu.m_temporalId); if (!pcSlice->getDependentSliceSegmentFlag()) { pcSlice->checkCRA(pcSlice->getRPS(), m_pocCRA, m_associatedIRAPType, m_cListPic); #if MCTS_EXTRACTION if (bSkipCabacAndReconstruction) { m_bFirstSliceInPicture = false; m_uiSliceIdx++; return false; } #endif // Set reference list pcSlice->setRefPicList( m_cListPic, true ); // For generalized B // note: maybe not existed case (always L0 is copied to L1 if L1 is empty) if (pcSlice->isInterB() && pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) { Int iNumRefIdx = pcSlice->getNumRefIdx(REF_PIC_LIST_0); pcSlice->setNumRefIdx ( REF_PIC_LIST_1, iNumRefIdx ); for (Int iRefIdx = 0; iRefIdx < iNumRefIdx; iRefIdx++) { pcSlice->setRefPic(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx), REF_PIC_LIST_1, iRefIdx); } } if (!pcSlice->isIntra()) { Bool bLowDelay = true; Int iCurrPOC = pcSlice->getPOC(); Int iRefIdx = 0; for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } if (pcSlice->isInterB()) { for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } } pcSlice->setCheckLDC(bLowDelay); } //--------------- pcSlice->setRefPOCList(); } m_pcPic->setCurrSliceIdx(m_uiSliceIdx); if(pcSlice->getSPS()->getScalingListFlag()) { TComScalingList scalingList; if(pcSlice->getPPS()->getScalingListPresentFlag()) { scalingList = pcSlice->getPPS()->getScalingList(); } else if (pcSlice->getSPS()->getScalingListPresentFlag()) { scalingList = pcSlice->getSPS()->getScalingList(); } else { scalingList.setDefaultScalingList(); } m_cTrQuant.setScalingListDec(scalingList); m_cTrQuant.setUseScalingList(true); } else { const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE] = { pcSlice->getSPS()->getMaxLog2TrDynamicRange(CHANNEL_TYPE_LUMA), pcSlice->getSPS()->getMaxLog2TrDynamicRange(CHANNEL_TYPE_CHROMA) }; m_cTrQuant.setFlatScalingList(maxLog2TrDynamicRange, pcSlice->getSPS()->getBitDepths()); m_cTrQuant.setUseScalingList(false); } // Decode a picture m_cGopDecoder.decompressSlice(&(nalu.getBitstream()), m_pcPic); m_bFirstSliceInPicture = false; m_uiSliceIdx++; return false; } Void TDecTop::xDecodeVPS(const std::vector &naluData) { TComVPS* vps = new TComVPS(); m_cEntropyDecoder.decodeVPS( vps ); m_parameterSetManager.storeVPS(vps, naluData); } Void TDecTop::xDecodeSPS(const std::vector &naluData) { TComSPS* sps = new TComSPS(); #if O0043_BEST_EFFORT_DECODING sps->setForceDecodeBitDepth(m_forceDecodeBitDepth); #endif m_cEntropyDecoder.decodeSPS( sps ); m_parameterSetManager.storeSPS(sps, naluData); } Void TDecTop::xDecodePPS(const std::vector &naluData) { TComPPS* pps = new TComPPS(); m_cEntropyDecoder.decodePPS( pps ); m_parameterSetManager.storePPS( pps, naluData); } #if MCTS_EXTRACTION Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay, Bool bSkipCabacAndReconstruction) #else Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay) #endif { // ignore all NAL units of layers > 0 if (nalu.m_nuhLayerId > 0) { fprintf (stderr, "Warning: found NAL unit with nuh_layer_id equal to %d. Ignoring.\n", nalu.m_nuhLayerId); return false; } // Initialize entropy decoder m_cEntropyDecoder.setEntropyDecoder (&m_cCavlcDecoder); m_cEntropyDecoder.setBitstream (&(nalu.getBitstream())); switch (nalu.m_nalUnitType) { case NAL_UNIT_VPS: xDecodeVPS(nalu.getBitstream().getFifo()); return false; case NAL_UNIT_SPS: xDecodeSPS(nalu.getBitstream().getFifo()); return false; case NAL_UNIT_PPS: xDecodePPS(nalu.getBitstream().getFifo()); return false; case NAL_UNIT_PREFIX_SEI: // Buffer up prefix SEI messages until SPS of associated VCL is known. m_prefixSEINALUs.push_back(new InputNALUnit(nalu)); return false; case NAL_UNIT_SUFFIX_SEI: if (m_pcPic) { m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->getSEIs(), nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_pDecodedSEIOutputStream ); } else { printf ("Note: received suffix SEI but no picture currently active.\n"); } return false; case NAL_UNIT_CODED_SLICE_TRAIL_R: case NAL_UNIT_CODED_SLICE_TRAIL_N: case NAL_UNIT_CODED_SLICE_TSA_R: case NAL_UNIT_CODED_SLICE_TSA_N: case NAL_UNIT_CODED_SLICE_STSA_R: case NAL_UNIT_CODED_SLICE_STSA_N: case NAL_UNIT_CODED_SLICE_BLA_W_LP: case NAL_UNIT_CODED_SLICE_BLA_W_RADL: case NAL_UNIT_CODED_SLICE_BLA_N_LP: case NAL_UNIT_CODED_SLICE_IDR_W_RADL: case NAL_UNIT_CODED_SLICE_IDR_N_LP: case NAL_UNIT_CODED_SLICE_CRA: case NAL_UNIT_CODED_SLICE_RADL_N: case NAL_UNIT_CODED_SLICE_RADL_R: case NAL_UNIT_CODED_SLICE_RASL_N: case NAL_UNIT_CODED_SLICE_RASL_R: #if MCTS_EXTRACTION return xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay, bSkipCabacAndReconstruction); #else return xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay); #endif break; case NAL_UNIT_EOS: m_associatedIRAPType = NAL_UNIT_INVALID; m_pocCRA = 0; m_pocRandomAccess = MAX_INT; m_prevPOC = MAX_INT; m_prevSliceSkipped = false; m_skippedPOC = 0; return false; case NAL_UNIT_ACCESS_UNIT_DELIMITER: { AUDReader audReader; UInt picType; audReader.parseAccessUnitDelimiter(&(nalu.getBitstream()),picType); printf ("Note: found NAL_UNIT_ACCESS_UNIT_DELIMITER\n"); return false; } case NAL_UNIT_EOB: return false; case NAL_UNIT_FILLER_DATA: { FDReader fdReader; UInt size; fdReader.parseFillerData(&(nalu.getBitstream()),size); printf ("Note: found NAL_UNIT_FILLER_DATA with %u bytes payload.\n", size); return false; } case NAL_UNIT_RESERVED_VCL_N10: case NAL_UNIT_RESERVED_VCL_R11: case NAL_UNIT_RESERVED_VCL_N12: case NAL_UNIT_RESERVED_VCL_R13: case NAL_UNIT_RESERVED_VCL_N14: case NAL_UNIT_RESERVED_VCL_R15: case NAL_UNIT_RESERVED_IRAP_VCL22: case NAL_UNIT_RESERVED_IRAP_VCL23: case NAL_UNIT_RESERVED_VCL24: case NAL_UNIT_RESERVED_VCL25: case NAL_UNIT_RESERVED_VCL26: case NAL_UNIT_RESERVED_VCL27: case NAL_UNIT_RESERVED_VCL28: case NAL_UNIT_RESERVED_VCL29: case NAL_UNIT_RESERVED_VCL30: case NAL_UNIT_RESERVED_VCL31: printf ("Note: found reserved VCL NAL unit.\n"); xParsePrefixSEIsForUnknownVCLNal(); return false; case NAL_UNIT_RESERVED_NVCL41: case NAL_UNIT_RESERVED_NVCL42: case NAL_UNIT_RESERVED_NVCL43: case NAL_UNIT_RESERVED_NVCL44: case NAL_UNIT_RESERVED_NVCL45: case NAL_UNIT_RESERVED_NVCL46: case NAL_UNIT_RESERVED_NVCL47: printf ("Note: found reserved NAL unit.\n"); return false; case NAL_UNIT_UNSPECIFIED_48: case NAL_UNIT_UNSPECIFIED_49: case NAL_UNIT_UNSPECIFIED_50: case NAL_UNIT_UNSPECIFIED_51: case NAL_UNIT_UNSPECIFIED_52: case NAL_UNIT_UNSPECIFIED_53: case NAL_UNIT_UNSPECIFIED_54: case NAL_UNIT_UNSPECIFIED_55: case NAL_UNIT_UNSPECIFIED_56: case NAL_UNIT_UNSPECIFIED_57: case NAL_UNIT_UNSPECIFIED_58: case NAL_UNIT_UNSPECIFIED_59: case NAL_UNIT_UNSPECIFIED_60: case NAL_UNIT_UNSPECIFIED_61: case NAL_UNIT_UNSPECIFIED_62: case NAL_UNIT_UNSPECIFIED_63: printf ("Note: found unspecified NAL unit.\n"); return false; default: assert (0); break; } return false; } /** Function for checking if picture should be skipped because of association with a previous BLA picture * \param iPOCLastDisplay POC of last picture displayed * \returns true if the picture should be skipped * This function skips all TFD pictures that follow a BLA picture * in decoding order and precede it in output order. */ Bool TDecTop::isSkipPictureForBLA(Int& iPOCLastDisplay) { if ((m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_N_LP || m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_W_LP || m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_W_RADL) && m_apcSlicePilot->getPOC() < m_pocCRA && (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N)) { iPOCLastDisplay++; return true; } return false; } /** Function for checking if picture should be skipped because of random access * \param iSkipFrame skip frame counter * \param iPOCLastDisplay POC of last picture displayed * \returns true if the picture shold be skipped in the random access. * This function checks the skipping of pictures in the case of -s option random access. * All pictures prior to the random access point indicated by the counter iSkipFrame are skipped. * It also checks the type of Nal unit type at the random access point. * If the random access point is CRA/CRANT/BLA/BLANT, TFD pictures with POC less than the POC of the random access point are skipped. * If the random access point is IDR all pictures after the random access point are decoded. * If the random access point is none of the above, a warning is issues, and decoding of pictures with POC * equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random * access point there is no guarantee that the decoder will not crash. */ Bool TDecTop::isRandomAccessSkipPicture(Int& iSkipFrame, Int& iPOCLastDisplay) { if (iSkipFrame) { iSkipFrame--; // decrement the counter return true; } else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet. { if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL ) { // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT. m_pocRandomAccess = m_apcSlicePilot->getPOC(); } else if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) { m_pocRandomAccess = -MAX_INT; // no need to skip the reordered pictures in IDR, they are decodable. } else { if(!m_warningMessageSkipPicture) { printf("\nWarning: this is not a valid random access point and the data is discarded until the first CRA picture"); m_warningMessageSkipPicture = true; } return true; } } // skip the reordered pictures, if necessary else if (m_apcSlicePilot->getPOC() < m_pocRandomAccess && (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N)) { iPOCLastDisplay++; return true; } // if we reach here, then the picture is not skipped. return false; } //! \} HM-HM-18.0/source/Lib/TLibDecoder/TDecTop.h000066400000000000000000000203531442026013100200450ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TDecTop.h \brief decoder class (header) */ #ifndef __TDECTOP__ #define __TDECTOP__ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComList.h" #include "TLibCommon/TComPicYuv.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComTrQuant.h" #include "TLibCommon/TComPrediction.h" #include "TLibCommon/SEI.h" #include "TDecGop.h" #include "TDecEntropy.h" #include "TDecSbac.h" #include "TDecCAVLC.h" #include "SEIread.h" #include "TDecConformance.h" class InputNALUnit; //! \ingroup TLibDecoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// decoder class class TDecTop { private: Int m_iMaxRefPicNum; NalUnitType m_associatedIRAPType; ///< NAL unit type of the associated IRAP picture Int m_pocCRA; ///< POC number of the latest CRA picture Int m_pocRandomAccess; ///< POC number of the random access point (the first IDR or CRA picture) TComList m_cListPic; // Dynamic buffer ParameterSetManager m_parameterSetManager; // storage for parameter sets TComSlice* m_apcSlicePilot; SEIMessages m_SEIs; ///< List of SEI messages that have been received before the first slice and between slices, excluding prefix SEIs... // functional classes TComPrediction m_cPrediction; TComTrQuant m_cTrQuant; TDecGop m_cGopDecoder; TDecSlice m_cSliceDecoder; TDecCu m_cCuDecoder; TDecEntropy m_cEntropyDecoder; TDecCavlc m_cCavlcDecoder; TDecSbac m_cSbacDecoder; TDecBinCABAC m_cBinCABAC; SEIReader m_seiReader; TComLoopFilter m_cLoopFilter; TComSampleAdaptiveOffset m_cSAO; TDecConformanceCheck m_conformanceCheck; Bool isSkipPictureForBLA(Int& iPOCLastDisplay); Bool isRandomAccessSkipPicture(Int& iSkipFrame, Int& iPOCLastDisplay); TComPic* m_pcPic; UInt m_uiSliceIdx; Int m_prevPOC; Int m_prevTid0POC; Bool m_bFirstSliceInPicture; #if JVET_X0048_X0103_FILM_GRAIN Bool m_bFirstPictureInSequence; SEIFilmGrainSynthesizer m_grainCharacteristic; TComPicYuv m_grainBuf; #endif Bool m_bFirstSliceInSequence; Bool m_prevSliceSkipped; Int m_skippedPOC; Bool m_bFirstSliceInBitstream; Int m_lastPOCNoOutputPriorPics; Bool m_isNoOutputPriorPics; Bool m_craNoRaslOutputFlag; //value of variable NoRaslOutputFlag of the last CRA pic #if SHUTTER_INTERVAL_SEI_PROCESSING Bool m_ShutterFilterEnable; // Shutter Interval SEI Processing #endif #if O0043_BEST_EFFORT_DECODING UInt m_forceDecodeBitDepth; #endif std::ostream *m_pDecodedSEIOutputStream; Bool m_warningMessageSkipPicture; #if MCTS_ENC_CHECK Bool m_tmctsCheckEnabled; #endif std::list m_prefixSEINALUs; /// Buffered up prefix SEI NAL Units. public: TDecTop(); virtual ~TDecTop(); Void create (); Void destroy (); Void setDecodedPictureHashSEIEnabled(Int enabled) { m_cGopDecoder.setDecodedPictureHashSEIEnabled(enabled); } #if MCTS_ENC_CHECK Void setTMctsCheckEnabled(Bool enabled) { m_tmctsCheckEnabled = enabled; } #endif Void init(); #if MCTS_EXTRACTION SEIMessages& getSEIs() { return m_SEIs; } TComSlice* getApcSlicePilot() { return m_apcSlicePilot; } TComPic* getPcPic() const { return m_pcPic; } Bool decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay, Bool bSkipCabacAndReconstruction=false); #else Bool decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay); #endif Void deletePicBuffer(); Void executeLoopFilters(Int& poc, TComList*& rpcListPic); Void checkNoOutputPriorPics (TComList* rpcListPic); Bool getNoOutputPriorPicsFlag () { return m_isNoOutputPriorPics; } Void setNoOutputPriorPicsFlag (Bool val) { m_isNoOutputPriorPics = val; } Void setFirstSliceInPicture (bool val) { m_bFirstSliceInPicture = val; } Bool getFirstSliceInSequence () { return m_bFirstSliceInSequence; } Void setFirstSliceInSequence (bool val) { m_bFirstSliceInSequence = val; } #if SHUTTER_INTERVAL_SEI_PROCESSING Bool getShutterFilterFlag () const { return m_ShutterFilterEnable; } Void setShutterFilterFlag (Bool value) { m_ShutterFilterEnable = value; } #endif #if O0043_BEST_EFFORT_DECODING Void setForceDecodeBitDepth(UInt bitDepth) { m_forceDecodeBitDepth = bitDepth; } #endif Void setDecodedSEIMessageOutputStream(std::ostream *pOpStream) { m_pDecodedSEIOutputStream = pOpStream; } UInt getNumberOfChecksumErrorsDetected() const { return m_cGopDecoder.getNumberOfChecksumErrorsDetected(); } protected: Void xGetNewPicBuffer (const TComSPS &sps, const TComPPS &pps, TComPic*& rpcPic, const UInt temporalLayer); Void xCreateLostPicture (Int iLostPOC); #if MCTS_EXTRACTION Bool xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay, Bool bSkipCabacAndReconstruction); Void xActivateParameterSets(Bool bSkipCabacAndReconstruction); #else Bool xDecodeSlice(InputNALUnit &nalu, Int &iSkipFrame, Int iPOCLastDisplay); Void xActivateParameterSets(); #endif Void xDecodeVPS(const std::vector &naluData); Void xDecodeSPS(const std::vector &naluData); Void xDecodePPS(const std::vector &naluData); Void xUpdatePreviousTid0POC( TComSlice *pSlice ) { if ((pSlice->getTLayer()==0) && (pSlice->isReferenceNalu() && (pSlice->getNalUnitType()!=NAL_UNIT_CODED_SLICE_RASL_R)&& (pSlice->getNalUnitType()!=NAL_UNIT_CODED_SLICE_RADL_R))) { m_prevTid0POC=pSlice->getPOC(); } } #if MCTS_EXTRACTION public: #endif TComList* getRpcListPic() { return &m_cListPic; }; Void xParsePrefixSEImessages(); #if MCTS_EXTRACTION private: #endif #if MCTS_ENC_CHECK Void xAnalysePrefixSEImessages(); #endif Void xParsePrefixSEIsForUnknownVCLNal(); };// END CLASS DEFINITION TDecTop //! \} #endif // __TDECTOP__ HM-HM-18.0/source/Lib/TLibDecoderAnalyser/000077500000000000000000000000001442026013100200665ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibDecoderAnalyser/CMakeLists.txt000066400000000000000000000024671442026013100226370ustar00rootroot00000000000000# library set( LIB_NAME TLibDecoderAnalyser ) # get source files file( GLOB SRC_FILES "../TLibDecoder/*.cpp" ) # get include files file( GLOB INC_FILES "../TLibDecoder/*.h" ) # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # library add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__DECODER_DEBUG_BIT_STATISTICS=1 ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__DECODER_DEBUG_TOOL_STATISTICS=1 ) if( HIGH_BITDEPTH ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( EXTENSION_360_VIDEO ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() target_include_directories( ${LIB_NAME} PUBLIC ../TLibDecoder . ..) target_link_libraries( ${LIB_NAME} TLibCommonAnalyser Threads::Threads ) # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib ) HM-HM-18.0/source/Lib/TLibEncoder/000077500000000000000000000000001442026013100164015ustar00rootroot00000000000000HM-HM-18.0/source/Lib/TLibEncoder/AnnexBwrite.h000066400000000000000000000067721442026013100210140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifndef __ANNEXBWRITE__ #define __ANNEXBWRITE__ #include #include "TLibCommon/AccessUnit.h" #include "NALwrite.h" //! \ingroup TLibEncoder //! \{ /** * write all NALunits in au to bytestream out in a manner satisfying * AnnexB of AVC. NALunits are written in the order they are found in au. * the zero_byte word is appended to: * - the initial startcode in the access unit, * - any SPS/PPS nal units */ static std::vector writeAnnexB(std::ostream& out, const AccessUnit& au) { std::vector annexBsizes; for (AccessUnit::const_iterator it = au.begin(); it != au.end(); it++) { const NALUnitEBSP& nalu = **it; UInt size = 0; /* size of annexB unit in bytes */ static const UChar start_code_prefix[] = {0,0,0,1}; if (it == au.begin() || nalu.m_nalUnitType == NAL_UNIT_VPS || nalu.m_nalUnitType == NAL_UNIT_SPS || nalu.m_nalUnitType == NAL_UNIT_PPS) { /* From AVC, When any of the following conditions are fulfilled, the * zero_byte syntax element shall be present: * - the nal_unit_type within the nal_unit() is equal to 7 (sequence * parameter set) or 8 (picture parameter set), * - the byte stream NAL unit syntax structure contains the first NAL * unit of an access unit in decoding order, as specified by subclause * 7.4.1.2.3. */ out.write(reinterpret_cast(start_code_prefix), 4); size += 4; } else { out.write(reinterpret_cast(start_code_prefix+1), 3); size += 3; } out << nalu.m_nalUnitData.str(); size += UInt(nalu.m_nalUnitData.str().size()); annexBsizes.push_back(size); } return annexBsizes; } //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/CMakeLists.txt000066400000000000000000000024501442026013100211420ustar00rootroot00000000000000# library set( LIB_NAME TLibEncoder ) # get source files file( GLOB SRC_FILES "*.cpp" ) # get include files file( GLOB INC_FILES "*.h" ) # NATVIS files for Visual Studio if( MSVC ) file( GLOB NATVIS_FILES "../../VisualStudio/*.natvis" ) endif() # library add_library( ${LIB_NAME} STATIC ${SRC_FILES} ${INC_FILES} ${NATVIS_FILES} ) target_compile_definitions( ${LIB_NAME} PUBLIC ) if( HIGH_BITDEPTH ) target_compile_definitions( ${LIB_NAME} PUBLIC RExt__HIGH_BIT_DEPTH_SUPPORT=1 ) endif() if( EXTENSION_360_VIDEO ) target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 ) endif() if( SET_ENABLE_TRACING ) if( ENABLE_TRACING ) target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 ) else() target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=0 ) endif() endif() target_include_directories( ${LIB_NAME} PUBLIC . ) target_link_libraries( ${LIB_NAME} TLibCommon Threads::Threads ) if( CMAKE_COMPILER_IS_GNUCC ) # this is quite certainly a compiler problem set_property( SOURCE "EncCu.cpp" APPEND PROPERTY COMPILE_FLAGS "-Wno-array-bounds" ) endif() # example: place header files in different folders source_group( "Natvis Files" FILES ${NATVIS_FILES} ) # set the folder where to place the projects set_target_properties( ${LIB_NAME} PROPERTIES FOLDER lib ) HM-HM-18.0/source/Lib/TLibEncoder/NALwrite.cpp000066400000000000000000000110441442026013100205720ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "TLibCommon/NAL.h" #include "TLibCommon/TComBitStream.h" #include "NALwrite.h" using namespace std; //! \ingroup TLibEncoder //! \{ static const UChar emulation_prevention_three_byte[] = {3}; Void writeNalUnitHeader(ostream& out, OutputNALUnit& nalu) // nal_unit_header() { TComOutputBitstream bsNALUHeader; bsNALUHeader.write(0,1); // forbidden_zero_bit bsNALUHeader.write(nalu.m_nalUnitType, 6); // nal_unit_type bsNALUHeader.write(nalu.m_nuhLayerId, 6); // nuh_layer_id bsNALUHeader.write(nalu.m_temporalId+1, 3); // nuh_temporal_id_plus1 out.write(reinterpret_cast(bsNALUHeader.getByteStream()), bsNALUHeader.getByteStreamLength()); } /** * write nalu to bytestream out, performing RBSP anti startcode * emulation as required. nalu.m_RBSPayload must be byte aligned. */ Void write(ostream& out, OutputNALUnit& nalu) { writeNalUnitHeader(out, nalu); /* write out rsbp_byte's, inserting any required * emulation_prevention_three_byte's */ /* 7.4.1 ... * emulation_prevention_three_byte is a byte equal to 0x03. When an * emulation_prevention_three_byte is present in the NAL unit, it shall be * discarded by the decoding process. * The last byte of the NAL unit shall not be equal to 0x00. * Within the NAL unit, the following three-byte sequences shall not occur at * any byte-aligned position: * - 0x000000 * - 0x000001 * - 0x000002 * Within the NAL unit, any four-byte sequence that starts with 0x000003 * other than the following sequences shall not occur at any byte-aligned * position: * - 0x00000300 * - 0x00000301 * - 0x00000302 * - 0x00000303 */ vector& rbsp = nalu.m_Bitstream.getFIFO(); vector outputBuffer; outputBuffer.resize(rbsp.size()*2+1); //there can never be enough emulation_prevention_three_bytes to require this much space std::size_t outputAmount = 0; Int zeroCount = 0; for (vector::iterator it = rbsp.begin(); it != rbsp.end(); it++) { const uint8_t v=(*it); if (zeroCount==2 && v<=3) { outputBuffer[outputAmount++]=emulation_prevention_three_byte[0]; zeroCount=0; } if (v==0) { zeroCount++; } else { zeroCount=0; } outputBuffer[outputAmount++]=v; } /* 7.4.1.1 * ... when the last byte of the RBSP data is equal to 0x00 (which can * only occur when the RBSP ends in a cabac_zero_word), a final byte equal * to 0x03 is appended to the end of the data. */ if (zeroCount>0) { outputBuffer[outputAmount++]=emulation_prevention_three_byte[0]; } out.write(reinterpret_cast(&(*outputBuffer.begin())), outputAmount); } //! \} HM-HM-18.0/source/Lib/TLibEncoder/NALwrite.h000066400000000000000000000055301442026013100202420ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifndef __NALWRITE__ #define __NALWRITE__ #include #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/NAL.h" //! \ingroup TLibEncoder //! \{ /** * A convenience wrapper to NALUnit that also provides a * bitstream object. */ struct OutputNALUnit : public NALUnit { /** * construct an OutputNALunit structure with given header values and * storage for a bitstream. Upon construction the NALunit header is * written to the bitstream. */ OutputNALUnit( NalUnitType nalUnitType, UInt temporalID = 0, UInt reserved_zero_6bits = 0) : NALUnit(nalUnitType, temporalID, reserved_zero_6bits) , m_Bitstream() {} OutputNALUnit& operator=(const NALUnit& src) { m_Bitstream.clear(); static_cast(this)->operator=(src); return *this; } TComOutputBitstream m_Bitstream; }; Void write(std::ostream& out, OutputNALUnit& nalu); inline NALUnitEBSP::NALUnitEBSP(OutputNALUnit& nalu) : NALUnit(nalu) { write(m_nalUnitData, nalu); } //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/SEIEncoder.cpp000066400000000000000000002253031442026013100210320ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "TLibCommon/CommonDef.h" #include "TLibCommon/SEI.h" #include "TEncGOP.h" #include "TEncTop.h" //! \ingroup TLibEncoder //! \{ Void SEIEncoder::initSEIActiveParameterSets (SEIActiveParameterSets *seiActiveParameterSets, const TComVPS *vps, const TComSPS *sps) { assert (m_isInitialized); assert (seiActiveParameterSets!=NULL); assert (vps!=NULL); assert (sps!=NULL); seiActiveParameterSets->activeVPSId = vps->getVPSId(); seiActiveParameterSets->m_selfContainedCvsFlag = false; seiActiveParameterSets->m_noParameterSetUpdateFlag = false; seiActiveParameterSets->numSpsIdsMinus1 = 0; seiActiveParameterSets->activeSeqParameterSetId.resize(seiActiveParameterSets->numSpsIdsMinus1 + 1); seiActiveParameterSets->activeSeqParameterSetId[0] = sps->getSPSId(); } Void SEIEncoder::initSEIFramePacking(SEIFramePacking *seiFramePacking, Int currPicNum) { assert (m_isInitialized); assert (seiFramePacking!=NULL); seiFramePacking->m_arrangementId = m_pcCfg->getFramePackingArrangementSEIId(); seiFramePacking->m_arrangementCancelFlag = 0; seiFramePacking->m_arrangementType = m_pcCfg->getFramePackingArrangementSEIType(); assert((seiFramePacking->m_arrangementType > 2) && (seiFramePacking->m_arrangementType < 6) ); seiFramePacking->m_quincunxSamplingFlag = m_pcCfg->getFramePackingArrangementSEIQuincunx(); seiFramePacking->m_contentInterpretationType = m_pcCfg->getFramePackingArrangementSEIInterpretation(); seiFramePacking->m_spatialFlippingFlag = 0; seiFramePacking->m_frame0FlippedFlag = 0; seiFramePacking->m_fieldViewsFlag = (seiFramePacking->m_arrangementType == 2); seiFramePacking->m_currentFrameIsFrame0Flag = ((seiFramePacking->m_arrangementType == 5) && (currPicNum&1) ); seiFramePacking->m_frame0SelfContainedFlag = 0; seiFramePacking->m_frame1SelfContainedFlag = 0; seiFramePacking->m_frame0GridPositionX = 0; seiFramePacking->m_frame0GridPositionY = 0; seiFramePacking->m_frame1GridPositionX = 0; seiFramePacking->m_frame1GridPositionY = 0; seiFramePacking->m_arrangementReservedByte = 0; seiFramePacking->m_arrangementPersistenceFlag = true; seiFramePacking->m_upsampledAspectRatio = 0; } Void SEIEncoder::initSEISegmentedRectFramePacking(SEISegmentedRectFramePacking *seiSegmentedRectFramePacking) { assert (m_isInitialized); assert (seiSegmentedRectFramePacking!=NULL); seiSegmentedRectFramePacking->m_arrangementCancelFlag = m_pcCfg->getSegmentedRectFramePackingArrangementSEICancel(); seiSegmentedRectFramePacking->m_contentInterpretationType = m_pcCfg->getSegmentedRectFramePackingArrangementSEIType(); seiSegmentedRectFramePacking->m_arrangementPersistenceFlag = m_pcCfg->getSegmentedRectFramePackingArrangementSEIPersistence(); } Void SEIEncoder::initSEIDisplayOrientation(SEIDisplayOrientation* seiDisplayOrientation) { assert (m_isInitialized); assert (seiDisplayOrientation!=NULL); seiDisplayOrientation->cancelFlag = false; seiDisplayOrientation->horFlip = false; seiDisplayOrientation->verFlip = false; seiDisplayOrientation->anticlockwiseRotation = m_pcCfg->getDisplayOrientationSEIAngle(); } Void SEIEncoder::initSEIToneMappingInfo(SEIToneMappingInfo *seiToneMappingInfo) { assert (m_isInitialized); assert (seiToneMappingInfo!=NULL); seiToneMappingInfo->m_toneMapId = m_pcCfg->getTMISEIToneMapId(); seiToneMappingInfo->m_toneMapCancelFlag = m_pcCfg->getTMISEIToneMapCancelFlag(); seiToneMappingInfo->m_toneMapPersistenceFlag = m_pcCfg->getTMISEIToneMapPersistenceFlag(); seiToneMappingInfo->m_codedDataBitDepth = m_pcCfg->getTMISEICodedDataBitDepth(); assert(seiToneMappingInfo->m_codedDataBitDepth >= 8 && seiToneMappingInfo->m_codedDataBitDepth <= 14); seiToneMappingInfo->m_targetBitDepth = m_pcCfg->getTMISEITargetBitDepth(); assert(seiToneMappingInfo->m_targetBitDepth >= 1 && seiToneMappingInfo->m_targetBitDepth <= 17); seiToneMappingInfo->m_modelId = m_pcCfg->getTMISEIModelID(); assert(seiToneMappingInfo->m_modelId >=0 &&seiToneMappingInfo->m_modelId<=4); switch( seiToneMappingInfo->m_modelId) { case 0: { seiToneMappingInfo->m_minValue = m_pcCfg->getTMISEIMinValue(); seiToneMappingInfo->m_maxValue = m_pcCfg->getTMISEIMaxValue(); break; } case 1: { seiToneMappingInfo->m_sigmoidMidpoint = m_pcCfg->getTMISEISigmoidMidpoint(); seiToneMappingInfo->m_sigmoidWidth = m_pcCfg->getTMISEISigmoidWidth(); break; } case 2: { UInt num = 1u<<(seiToneMappingInfo->m_targetBitDepth); seiToneMappingInfo->m_startOfCodedInterval.resize(num); Int* ptmp = m_pcCfg->getTMISEIStartOfCodedInterva(); if(ptmp) { for(Int i=0; im_startOfCodedInterval[i] = ptmp[i]; } } break; } case 3: { seiToneMappingInfo->m_numPivots = m_pcCfg->getTMISEINumPivots(); seiToneMappingInfo->m_codedPivotValue.resize(seiToneMappingInfo->m_numPivots); seiToneMappingInfo->m_targetPivotValue.resize(seiToneMappingInfo->m_numPivots); Int* ptmpcoded = m_pcCfg->getTMISEICodedPivotValue(); Int* ptmptarget = m_pcCfg->getTMISEITargetPivotValue(); if(ptmpcoded&&ptmptarget) { for(Int i=0; i<(seiToneMappingInfo->m_numPivots);i++) { seiToneMappingInfo->m_codedPivotValue[i]=ptmpcoded[i]; seiToneMappingInfo->m_targetPivotValue[i]=ptmptarget[i]; } } break; } case 4: { seiToneMappingInfo->m_cameraIsoSpeedIdc = m_pcCfg->getTMISEICameraIsoSpeedIdc(); seiToneMappingInfo->m_cameraIsoSpeedValue = m_pcCfg->getTMISEICameraIsoSpeedValue(); assert( seiToneMappingInfo->m_cameraIsoSpeedValue !=0 ); seiToneMappingInfo->m_exposureIndexIdc = m_pcCfg->getTMISEIExposurIndexIdc(); seiToneMappingInfo->m_exposureIndexValue = m_pcCfg->getTMISEIExposurIndexValue(); assert( seiToneMappingInfo->m_exposureIndexValue !=0 ); seiToneMappingInfo->m_exposureCompensationValueSignFlag = m_pcCfg->getTMISEIExposureCompensationValueSignFlag(); seiToneMappingInfo->m_exposureCompensationValueNumerator = m_pcCfg->getTMISEIExposureCompensationValueNumerator(); seiToneMappingInfo->m_exposureCompensationValueDenomIdc = m_pcCfg->getTMISEIExposureCompensationValueDenomIdc(); seiToneMappingInfo->m_refScreenLuminanceWhite = m_pcCfg->getTMISEIRefScreenLuminanceWhite(); seiToneMappingInfo->m_extendedRangeWhiteLevel = m_pcCfg->getTMISEIExtendedRangeWhiteLevel(); assert( seiToneMappingInfo->m_extendedRangeWhiteLevel >= 100 ); seiToneMappingInfo->m_nominalBlackLevelLumaCodeValue = m_pcCfg->getTMISEINominalBlackLevelLumaCodeValue(); seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue = m_pcCfg->getTMISEINominalWhiteLevelLumaCodeValue(); assert( seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue > seiToneMappingInfo->m_nominalBlackLevelLumaCodeValue ); seiToneMappingInfo->m_extendedWhiteLevelLumaCodeValue = m_pcCfg->getTMISEIExtendedWhiteLevelLumaCodeValue(); assert( seiToneMappingInfo->m_extendedWhiteLevelLumaCodeValue >= seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue ); break; } default: { assert(!"Undefined SEIToneMapModelId"); break; } } } Void SEIEncoder::initSEISOPDescription(SEISOPDescription *sopDescriptionSEI, TComSlice *slice, Int picInGOP, Int lastIdr, Int currGOPSize) { assert (m_isInitialized); assert (sopDescriptionSEI != NULL); assert (slice != NULL); Int sopCurrPOC = slice->getPOC(); sopDescriptionSEI->m_sopSeqParameterSetId = slice->getSPS()->getSPSId(); Int i = 0; Int prevEntryId = picInGOP; for (Int j = picInGOP; j < currGOPSize; j++) { Int deltaPOC = m_pcCfg->getGOPEntry(j).m_POC - m_pcCfg->getGOPEntry(prevEntryId).m_POC; if ((sopCurrPOC + deltaPOC) < m_pcCfg->getFramesToBeEncoded()) { sopCurrPOC += deltaPOC; sopDescriptionSEI->m_sopDescVclNaluType[i] = m_pcEncGOP->getNalUnitType(sopCurrPOC, lastIdr, slice->getPic()->isField()); sopDescriptionSEI->m_sopDescTemporalId[i] = m_pcCfg->getGOPEntry(j).m_temporalId; sopDescriptionSEI->m_sopDescStRpsIdx[i] = m_pcEncTop->getReferencePictureSetIdxForSOP(sopCurrPOC, j); sopDescriptionSEI->m_sopDescPocDelta[i] = deltaPOC; prevEntryId = j; i++; } } sopDescriptionSEI->m_numPicsInSopMinus1 = i - 1; } Void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, TComSlice *slice) { assert (m_isInitialized); assert (bufferingPeriodSEI != NULL); assert (slice != NULL); UInt uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec bufferingPeriodSEI->m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; Double dTmp = (Double)slice->getSPS()->getVuiParameters()->getTimingInfo()->getNumUnitsInTick() / (Double)slice->getSPS()->getVuiParameters()->getTimingInfo()->getTimeScale(); UInt uiTmp = (UInt)( dTmp * 90000.0 ); uiInitialCpbRemovalDelay -= uiTmp; uiInitialCpbRemovalDelay -= uiTmp / ( slice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2 ); bufferingPeriodSEI->m_initialAltCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialAltCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialAltCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialAltCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_rapCpbParamsPresentFlag = 0; //for the concatenation, it can be set to one during splicing. bufferingPeriodSEI->m_concatenationFlag = 0; //since the temporal layer HRD is not ready, we assumed it is fixed bufferingPeriodSEI->m_auCpbRemovalDelayDelta = 1; bufferingPeriodSEI->m_cpbDelayOffset = 0; bufferingPeriodSEI->m_dpbDelayOffset = 0; } //! initialize scalable nesting SEI message. //! Note: The SEI message structures input into this function will become part of the scalable nesting SEI and will be //! automatically freed, when the nesting SEI is disposed. Void SEIEncoder::initSEIScalableNesting(SEIScalableNesting *scalableNestingSEI, SEIMessages &nestedSEIs) { assert (m_isInitialized); assert (scalableNestingSEI != NULL); scalableNestingSEI->m_bitStreamSubsetFlag = 1; // If the nested SEI messages are picture buffering SEI messages, picture timing SEI messages or sub-picture timing SEI messages, bitstream_subset_flag shall be equal to 1 scalableNestingSEI->m_nestingOpFlag = 0; scalableNestingSEI->m_nestingNumOpsMinus1 = 0; //nesting_num_ops_minus1 scalableNestingSEI->m_allLayersFlag = 0; scalableNestingSEI->m_nestingNoOpMaxTemporalIdPlus1 = 6 + 1; //nesting_no_op_max_temporal_id_plus1 scalableNestingSEI->m_nestingNumLayersMinus1 = 1 - 1; //nesting_num_layers_minus1 scalableNestingSEI->m_nestingLayerId[0] = 0; scalableNestingSEI->m_nestedSEIs.clear(); for (SEIMessages::iterator it=nestedSEIs.begin(); it!=nestedSEIs.end(); it++) { scalableNestingSEI->m_nestedSEIs.push_back((*it)); } } Void SEIEncoder::initSEIRecoveryPoint(SEIRecoveryPoint *recoveryPointSEI, TComSlice *slice) { assert (m_isInitialized); assert (recoveryPointSEI != NULL); assert (slice != NULL); recoveryPointSEI->m_recoveryPocCnt = 0; recoveryPointSEI->m_exactMatchingFlag = ( slice->getPOC() == 0 ) ? (true) : (false); recoveryPointSEI->m_brokenLinkFlag = false; } //! calculate hashes for entire reconstructed picture Void SEIEncoder::initDecodedPictureHashSEI(SEIDecodedPictureHash *decodedPictureHashSEI, TComPic *pcPic, std::string &rHashString, const BitDepths &bitDepths) { assert (m_isInitialized); assert (decodedPictureHashSEI!=NULL); assert (pcPic!=NULL); decodedPictureHashSEI->method = m_pcCfg->getDecodedPictureHashSEIType(); switch (m_pcCfg->getDecodedPictureHashSEIType()) { case HASHTYPE_MD5: { UInt numChar=calcMD5(*pcPic->getPicYuvRec(), decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; case HASHTYPE_CRC: { UInt numChar=calcCRC(*pcPic->getPicYuvRec(), decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; case HASHTYPE_CHECKSUM: default: { UInt numChar=calcChecksum(*pcPic->getPicYuvRec(), decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; } } Void SEIEncoder::initTemporalLevel0IndexSEI(SEITemporalLevel0Index *temporalLevel0IndexSEI, TComSlice *slice) { assert (m_isInitialized); assert (temporalLevel0IndexSEI!=NULL); assert (slice!=NULL); if (slice->getRapPicFlag()) { m_tl0Idx = 0; m_rapIdx = (m_rapIdx + 1) & 0xFF; } else { m_tl0Idx = (m_tl0Idx + (slice->getTLayer() ? 0 : 1)) & 0xFF; } temporalLevel0IndexSEI->tl0Idx = m_tl0Idx; temporalLevel0IndexSEI->rapIdx = m_rapIdx; } Void SEIEncoder::initSEITempMotionConstrainedTileSets (SEITempMotionConstrainedTileSets *sei, const TComPPS *pps) { assert (m_isInitialized); assert (sei!=NULL); assert (pps!=NULL); if(pps->getTilesEnabledFlag()) { #if MCTS_ENC_CHECK if (m_pcCfg->getTMCTSSEITileConstraint()) { sei->m_mc_all_tiles_exact_sample_value_match_flag = true; sei->m_each_tile_one_tile_set_flag = true; sei->m_limited_tile_set_display_flag = false; sei->m_max_mcs_tier_level_idc_present_flag = false; sei->setNumberOfTileSets(0); } else { #endif sei->m_mc_all_tiles_exact_sample_value_match_flag = false; sei->m_each_tile_one_tile_set_flag = false; sei->m_limited_tile_set_display_flag = false; sei->setNumberOfTileSets((pps->getNumTileColumnsMinus1() + 1) * (pps->getNumTileRowsMinus1() + 1)); for(Int i=0; i < sei->getNumberOfTileSets(); i++) { sei->tileSetData(i).m_mcts_id = i; //depends the application; sei->tileSetData(i).setNumberOfTileRects(1); for(Int j=0; jtileSetData(i).getNumberOfTileRects(); j++) { sei->tileSetData(i).topLeftTileIndex(j) = i+j; sei->tileSetData(i).bottomRightTileIndex(j) = i+j; } sei->tileSetData(i).m_exact_sample_value_match_flag = false; sei->tileSetData(i).m_mcts_tier_level_idc_present_flag = false; } #if MCTS_ENC_CHECK } #endif } else { assert(!"Tile is not enabled"); } } #if MCTS_EXTRACTION && MCTS_ENC_CHECK Void SEIEncoder::initSEIMCTSExtractionInfo(SEIMCTSExtractionInfoSet *sei, const TComVPS *vps, const TComSPS *sps, const TComPPS *pps) { assert(m_isInitialized); assert(sei != NULL); assert(vps != NULL); assert(sps != NULL); assert(pps != NULL); TComVPS nestedVPS = *vps; TComSPS nestedSPS = *sps; TComPPS nestedPPS = *pps; if (pps->getTilesEnabledFlag()) { if (m_pcCfg->getTMCTSSEITileConstraint()) { UInt numTiles = (pps->getNumTileColumnsMinus1() + 1) * (pps->getNumTileRowsMinus1() + 1); UInt bottomTileRowHeightSampleOffset = ( sps->getPicHeightInLumaSamples() % sps->getMaxCUHeight() ) ? sps->getMaxCUHeight() - (sps->getPicHeightInLumaSamples() % sps->getMaxCUHeight()) : 0; UInt rightmostTileColumnWidthSampleOffset = ( sps->getPicWidthInLumaSamples() % sps->getMaxCUWidth() ) ? sps->getMaxCUWidth() - (sps->getPicWidthInLumaSamples() % sps->getMaxCUWidth()) : 0; TComPicSym *picSym = (*(m_pcEncTop->getListPic()->begin()))->getPicSym(); // find MCTS that may share similar extraction info for ( UInt mctsIdx = 0; mctsIdx < numTiles; mctsIdx++) { bool suitableEISfound = false; bool isRightmostTileColumn = (mctsIdx + 1) % (picSym->getNumTileColumnsMinus1() + 1) == 0 ; bool isBottomTileRow = mctsIdx / (picSym->getNumTileColumnsMinus1() + 1) == picSym->getNumTileRowsMinus1(); UInt curMctsHeight = picSym->getTComTile(mctsIdx)->getTileHeightInCtus() * sps->getMaxCUHeight() - (isBottomTileRow ? bottomTileRowHeightSampleOffset : 0); UInt curMctsWidth = picSym->getTComTile(mctsIdx)->getTileWidthInCtus() * sps->getMaxCUWidth() - (isRightmostTileColumn ? rightmostTileColumnWidthSampleOffset : 0); for (std::vector< SEIMCTSExtractionInfoSet::MCTSExtractionInfo>::iterator EISiter = sei->m_MCTSExtractionInfoSets.begin(); EISiter != sei->m_MCTSExtractionInfoSets.end() && !suitableEISfound; EISiter++) { if ( ( EISiter->mctsHeight == curMctsHeight) && ( EISiter->mctsWidth == curMctsWidth) ) { EISiter->m_idxOfMctsInSet.push_back(std::vector(1, mctsIdx )); suitableEISfound = true; } } if (!suitableEISfound) { SEIMCTSExtractionInfoSet::MCTSExtractionInfo newEIS; newEIS.mctsHeight = curMctsHeight; newEIS.mctsWidth = curMctsWidth; newEIS.m_idxOfMctsInSet.push_back(std::vector(1, mctsIdx)); sei->m_MCTSExtractionInfoSets.push_back(newEIS); } } // create parameter sets for each extraction info for (std::vector::iterator EISiter = sei->m_MCTSExtractionInfoSets.begin(); EISiter != sei->m_MCTSExtractionInfoSets.end(); EISiter++) { EISiter->m_sliceReorderingEnabledFlag = false; TComOutputBitstream vps_rbsp; TComOutputBitstream sps_rbsp; TComOutputBitstream pps_rbsp; nestedSPS.setPicHeightInLumaSamples(EISiter->mctsHeight); nestedSPS.setPicWidthInLumaSamples(EISiter->mctsWidth); nestedPPS.setTilesEnabledFlag(false); m_pcEncGOP->generateVPS_RBSP(&vps_rbsp, &nestedVPS); m_pcEncGOP->generateSPS_RBSP(&sps_rbsp, &nestedSPS); m_pcEncGOP->generatePPS_RBSP(&pps_rbsp, &nestedPPS); EISiter->m_vpsRbspData.resize(1); for (int j = 0; j < EISiter->m_vpsRbspData.size(); j++) { EISiter->m_vpsRbspDataLength.push_back(vps_rbsp.getByteStreamLength()); EISiter->m_vpsRbspData[j] = vps_rbsp.getFIFO(); } EISiter->m_spsRbspData.resize(1); for (int j = 0; j < EISiter->m_spsRbspData.size(); j++) { EISiter->m_spsRbspDataLength.push_back(sps_rbsp.getByteStreamLength()); EISiter->m_spsRbspData[j] = sps_rbsp.getFIFO(); } EISiter->m_ppsRbspData.resize(1); EISiter->m_ppsNuhTemporalIdPlus1.resize(1); for (int j = 0; j < EISiter->m_ppsRbspData.size(); j++) { EISiter->m_ppsRbspDataLength.push_back(pps_rbsp.getByteStreamLength()); EISiter->m_ppsRbspData[j] = pps_rbsp.getFIFO(); EISiter->m_ppsNuhTemporalIdPlus1[j] = 1; } } } else { assert(!"MCTS not activated"); } } else { assert(!"Tiles is not enabled"); } } #endif Void SEIEncoder::initSEIKneeFunctionInfo(SEIKneeFunctionInfo *seiKneeFunctionInfo) { assert (m_isInitialized); assert (seiKneeFunctionInfo!=NULL); const TEncCfg::TEncSEIKneeFunctionInformation &knee=m_pcCfg->getKneeFunctionInformationSEI(); seiKneeFunctionInfo->m_kneeId = knee.m_kneeFunctionId; seiKneeFunctionInfo->m_kneeCancelFlag = knee.m_kneeFunctionCancelFlag; if ( !seiKneeFunctionInfo->m_kneeCancelFlag ) { seiKneeFunctionInfo->m_kneePersistenceFlag = knee.m_kneeFunctionPersistenceFlag; seiKneeFunctionInfo->m_kneeInputDrange = knee.m_inputDRange; seiKneeFunctionInfo->m_kneeInputDispLuminance = knee.m_inputDispLuminance; seiKneeFunctionInfo->m_kneeOutputDrange = knee.m_outputDRange; seiKneeFunctionInfo->m_kneeOutputDispLuminance = knee.m_outputDispLuminance; assert(knee.m_kneeSEIKneePointPairs.size()>0); seiKneeFunctionInfo->m_kneeNumKneePointsMinus1 = (Int) knee.m_kneeSEIKneePointPairs.size()-1; seiKneeFunctionInfo->m_kneeInputKneePoint.resize(seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1); seiKneeFunctionInfo->m_kneeOutputKneePoint.resize(seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1); for(Int i=0; i<=seiKneeFunctionInfo->m_kneeNumKneePointsMinus1; i++) { seiKneeFunctionInfo->m_kneeInputKneePoint[i] = knee.m_kneeSEIKneePointPairs[i].inputKneePoint; seiKneeFunctionInfo->m_kneeOutputKneePoint[i] = knee.m_kneeSEIKneePointPairs[i].outputKneePoint; } } } Void SEIEncoder::initSEIContentColourVolume(SEIContentColourVolume *seiContentColourVolume) { assert(m_isInitialized); assert(seiContentColourVolume != NULL); seiContentColourVolume->m_ccvCancelFlag = m_pcCfg->getCcvSEICancelFlag(); seiContentColourVolume->m_ccvPersistenceFlag = m_pcCfg->getCcvSEIPersistenceFlag(); seiContentColourVolume->m_ccvPrimariesPresentFlag = m_pcCfg->getCcvSEIPrimariesPresentFlag(); seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag = m_pcCfg->getCcvSEIMinLuminanceValuePresentFlag(); seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag = m_pcCfg->getCcvSEIMaxLuminanceValuePresentFlag(); seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag = m_pcCfg->getCcvSEIAvgLuminanceValuePresentFlag(); // Currently we are using a floor operation for setting up the "integer" values for this SEI. // This applies to both primaries and luminance limits. if (seiContentColourVolume->m_ccvPrimariesPresentFlag == true) { for (Int i = 0; i < MAX_NUM_COMPONENT; i++) { seiContentColourVolume->m_ccvPrimariesX[i] = (Int) (50000.0 * m_pcCfg->getCcvSEIPrimariesX(i)); seiContentColourVolume->m_ccvPrimariesY[i] = (Int) (50000.0 * m_pcCfg->getCcvSEIPrimariesY(i)); } } if (seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvMinLuminanceValue = (Int) (10000000 * m_pcCfg->getCcvSEIMinLuminanceValue()); } if (seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvMaxLuminanceValue = (Int) (10000000 * m_pcCfg->getCcvSEIMaxLuminanceValue()); } if (seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvAvgLuminanceValue = (Int) (10000000 * m_pcCfg->getCcvSEIAvgLuminanceValue()); } } #if SHUTTER_INTERVAL_SEI_MESSAGE Void SEIEncoder::initSEIShutterIntervalInfo(SEIShutterIntervalInfo *seiShutterIntervalInfo) { assert(m_isInitialized); assert(seiShutterIntervalInfo != NULL); seiShutterIntervalInfo->m_siiTimeScale = m_pcCfg->getSiiSEITimeScale(); seiShutterIntervalInfo->m_siiFixedSIwithinCLVS = m_pcCfg->getSiiSEIFixedSIwithinCLVS(); if (seiShutterIntervalInfo->m_siiFixedSIwithinCLVS == true) { seiShutterIntervalInfo->m_siiNumUnitsInShutterInterval = m_pcCfg->getSiiSEINumUnitsInShutterInterval(); } else { seiShutterIntervalInfo->m_siiMaxSubLayersMinus1 = m_pcCfg->getSiiSEIMaxSubLayersMinus1(); seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI.resize(seiShutterIntervalInfo->m_siiMaxSubLayersMinus1+1); for (Int i = 0; i <= seiShutterIntervalInfo->m_siiMaxSubLayersMinus1; i++) { seiShutterIntervalInfo->m_siiSubLayerNumUnitsInSI[i] = m_pcCfg->getSiiSEISubLayerNumUnitsInSI(i); } } } #endif #if SEI_ENCODER_CONTROL Void SEIEncoder::initSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics *seiFilmGrain) { assert(m_isInitialized); assert(seiFilmGrain != NULL); // Set SEI message parameters read from command line options seiFilmGrain->m_filmGrainCharacteristicsCancelFlag = m_pcCfg->getFilmGrainCharactersticsSEICancelFlag(); seiFilmGrain->m_filmGrainCharacteristicsPersistenceFlag = m_pcCfg->getFilmGrainCharactersticsSEIPersistenceFlag(); seiFilmGrain->m_filmGrainModelId = m_pcCfg->getFilmGrainCharactersticsSEIModelID(); seiFilmGrain->m_separateColourDescriptionPresentFlag = m_pcCfg->getFilmGrainCharactersticsSEISepColourDescPresent(); seiFilmGrain->m_blendingModeId = m_pcCfg->getFilmGrainCharactersticsSEIBlendingModeID(); seiFilmGrain->m_log2ScaleFactor = m_pcCfg->getFilmGrainCharactersticsSEILog2ScaleFactor(); for (int i = 0; i < MAX_NUM_COMPONENT; i++) { seiFilmGrain->m_compModel[i].bPresentFlag = m_pcCfg->getFGCSEICompModelPresent(i); #if JVET_X0048_X0103_FILM_GRAIN if (seiFilmGrain->m_compModel[i].bPresentFlag) { seiFilmGrain->m_compModel[i].numModelValues = 1 + m_pcCfg->getFGCSEINumModelValuesMinus1(i); seiFilmGrain->m_compModel[i].numIntensityIntervals = 1 + m_pcCfg->getFGCSEINumIntensityIntervalMinus1(i); seiFilmGrain->m_compModel[i].intensityValues.resize(seiFilmGrain->m_compModel[i].numIntensityIntervals); for (UInt j = 0; j < seiFilmGrain->m_compModel[i].numIntensityIntervals; j++) { seiFilmGrain->m_compModel[i].intensityValues[j].intensityIntervalLowerBound = m_pcCfg->getFGCSEIIntensityIntervalLowerBound(i, j); seiFilmGrain->m_compModel[i].intensityValues[j].intensityIntervalUpperBound = m_pcCfg->getFGCSEIIntensityIntervalUpperBound(i, j); seiFilmGrain->m_compModel[i].intensityValues[j].compModelValue.resize(seiFilmGrain->m_compModel[i].numModelValues); for (UInt k = 0; k < seiFilmGrain->m_compModel[i].numModelValues; k++) { seiFilmGrain->m_compModel[i].intensityValues[j].compModelValue[k] = m_pcCfg->getFGCSEICompModelValue(i, j, k); } } } #endif } } Void SEIEncoder::initSEIContentLightLevel(SEIContentLightLevelInfo *seiCLL) { assert(m_isInitialized); assert(seiCLL != NULL); // Set SEI message parameters read from command line options seiCLL->m_maxContentLightLevel = m_pcCfg->getCLLSEIMaxContentLightLevel(); seiCLL->m_maxPicAverageLightLevel = m_pcCfg->getCLLSEIMaxPicAvgLightLevel(); } Void SEIEncoder::initSEIAmbientViewingEnvironment(SEIAmbientViewingEnvironment *seiAmbViewEnvironment) { assert(m_isInitialized); assert(seiAmbViewEnvironment != NULL); // Set SEI message parameters read from command line options seiAmbViewEnvironment->m_ambientIlluminance = m_pcCfg->getAmbientViewingEnvironmentSEIIlluminance(); seiAmbViewEnvironment->m_ambientLightX = m_pcCfg->getAmbientViewingEnvironmentSEIAmbientLightX(); seiAmbViewEnvironment->m_ambientLightY = m_pcCfg->getAmbientViewingEnvironmentSEIAmbientLightY(); } #endif Void SEIEncoder::initSEIErp(SEIEquirectangularProjection* seiEquirectangularProjection) { assert (m_isInitialized); assert (seiEquirectangularProjection!=NULL); seiEquirectangularProjection->m_erpCancelFlag = m_pcCfg->getErpSEICancelFlag(); if (!seiEquirectangularProjection->m_erpCancelFlag) { seiEquirectangularProjection->m_erpPersistenceFlag = m_pcCfg->getErpSEIPersistenceFlag(); seiEquirectangularProjection->m_erpGuardBandFlag = m_pcCfg->getErpSEIGuardBandFlag(); if (seiEquirectangularProjection->m_erpGuardBandFlag == 1) { seiEquirectangularProjection->m_erpGuardBandType = m_pcCfg->getErpSEIGuardBandType(); seiEquirectangularProjection->m_erpLeftGuardBandWidth = m_pcCfg->getErpSEILeftGuardBandWidth(); seiEquirectangularProjection->m_erpRightGuardBandWidth = m_pcCfg->getErpSEIRightGuardBandWidth(); } } } Void SEIEncoder::initSEISphereRotation(SEISphereRotation* seiSphereRotation) { assert (m_isInitialized); assert (seiSphereRotation!=NULL); seiSphereRotation->m_sphereRotationCancelFlag = m_pcCfg->getSphereRotationSEICancelFlag(); if ( !seiSphereRotation->m_sphereRotationCancelFlag ) { seiSphereRotation->m_sphereRotationPersistenceFlag = m_pcCfg->getSphereRotationSEIPersistenceFlag(); seiSphereRotation->m_sphereRotationYaw = m_pcCfg->getSphereRotationSEIYaw(); seiSphereRotation->m_sphereRotationPitch = m_pcCfg->getSphereRotationSEIPitch(); seiSphereRotation->m_sphereRotationRoll = m_pcCfg->getSphereRotationSEIRoll(); } } Void SEIEncoder::initSEIOmniViewport(SEIOmniViewport* seiOmniViewport) { assert (m_isInitialized); assert (seiOmniViewport!=NULL); seiOmniViewport->m_omniViewportId = m_pcCfg->getOmniViewportSEIId(); seiOmniViewport->m_omniViewportCancelFlag = m_pcCfg->getOmniViewportSEICancelFlag(); if ( !seiOmniViewport->m_omniViewportCancelFlag ) { seiOmniViewport->m_omniViewportPersistenceFlag = m_pcCfg->getOmniViewportSEIPersistenceFlag(); seiOmniViewport->m_omniViewportCntMinus1 = m_pcCfg->getOmniViewportSEICntMinus1(); seiOmniViewport->m_omniViewportRegions.resize(seiOmniViewport->m_omniViewportCntMinus1+1); for (UInt i = 0; i <= seiOmniViewport->m_omniViewportCntMinus1; i++) { SEIOmniViewport::OmniViewport &viewport = seiOmniViewport->m_omniViewportRegions[i]; viewport.azimuthCentre = m_pcCfg->getOmniViewportSEIAzimuthCentre(i); viewport.elevationCentre = m_pcCfg->getOmniViewportSEIElevationCentre(i); viewport.tiltCentre = m_pcCfg->getOmniViewportSEITiltCentre(i); viewport.horRange = m_pcCfg->getOmniViewportSEIHorRange(i); viewport.verRange = m_pcCfg->getOmniViewportSEIVerRange(i); } } } Void SEIEncoder::initSEICubemapProjection(SEICubemapProjection *seiCubemapProjection) { assert(m_isInitialized); assert(seiCubemapProjection != NULL); seiCubemapProjection->m_cmpCancelFlag = m_pcCfg->getCmpSEICmpCancelFlag(); seiCubemapProjection->m_cmpPersistenceFlag = m_pcCfg->getCmpSEICmpPersistenceFlag(); } Void SEIEncoder::initSEIRegionWisePacking(SEIRegionWisePacking *seiRegionWisePacking) { assert (m_isInitialized); assert (seiRegionWisePacking!=NULL); seiRegionWisePacking->m_rwpCancelFlag = m_pcCfg->getRwpSEIRwpCancelFlag(); seiRegionWisePacking->m_rwpPersistenceFlag = m_pcCfg->getRwpSEIRwpPersistenceFlag(); seiRegionWisePacking->m_constituentPictureMatchingFlag = m_pcCfg->getRwpSEIConstituentPictureMatchingFlag(); seiRegionWisePacking->m_numPackedRegions = m_pcCfg->getRwpSEINumPackedRegions(); seiRegionWisePacking->m_projPictureWidth = m_pcCfg->getRwpSEIProjPictureWidth(); seiRegionWisePacking->m_projPictureHeight = m_pcCfg->getRwpSEIProjPictureHeight(); seiRegionWisePacking->m_packedPictureWidth = m_pcCfg->getRwpSEIPackedPictureWidth(); seiRegionWisePacking->m_packedPictureHeight = m_pcCfg->getRwpSEIPackedPictureHeight(); seiRegionWisePacking->m_rwpTransformType.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandFlag.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpProjRegionTop.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionLeft.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionTop.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionLeft.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpLeftGuardBandWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpRightGuardBandWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpTopGuardBandHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpBottomGuardBandHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandNotUsedForPredFlag.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandType.resize(4*seiRegionWisePacking->m_numPackedRegions); for( Int i=0; i < seiRegionWisePacking->m_numPackedRegions; i++ ) { seiRegionWisePacking->m_rwpTransformType[i] = m_pcCfg->getRwpSEIRwpTransformType(i); seiRegionWisePacking->m_rwpGuardBandFlag[i] = m_pcCfg->getRwpSEIRwpGuardBandFlag(i); seiRegionWisePacking->m_projRegionWidth[i] = m_pcCfg->getRwpSEIProjRegionWidth(i); seiRegionWisePacking->m_projRegionHeight[i] = m_pcCfg->getRwpSEIProjRegionHeight(i); seiRegionWisePacking->m_rwpProjRegionTop[i] = m_pcCfg->getRwpSEIRwpSEIProjRegionTop(i); seiRegionWisePacking->m_projRegionLeft[i] = m_pcCfg->getRwpSEIProjRegionLeft(i); seiRegionWisePacking->m_packedRegionWidth[i] = m_pcCfg->getRwpSEIPackedRegionWidth(i); seiRegionWisePacking->m_packedRegionHeight[i] = m_pcCfg->getRwpSEIPackedRegionHeight(i); seiRegionWisePacking->m_packedRegionTop[i] = m_pcCfg->getRwpSEIPackedRegionTop(i); seiRegionWisePacking->m_packedRegionLeft[i] = m_pcCfg->getRwpSEIPackedRegionLeft(i); if( seiRegionWisePacking->m_rwpGuardBandFlag[i] ) { seiRegionWisePacking->m_rwpLeftGuardBandWidth[i] = m_pcCfg->getRwpSEIRwpLeftGuardBandWidth(i); seiRegionWisePacking->m_rwpRightGuardBandWidth[i] = m_pcCfg->getRwpSEIRwpRightGuardBandWidth(i); seiRegionWisePacking->m_rwpTopGuardBandHeight[i] = m_pcCfg->getRwpSEIRwpTopGuardBandHeight(i); seiRegionWisePacking->m_rwpBottomGuardBandHeight[i] = m_pcCfg->getRwpSEIRwpBottomGuardBandHeight(i); seiRegionWisePacking->m_rwpGuardBandNotUsedForPredFlag[i] = m_pcCfg->getRwpSEIRwpGuardBandNotUsedForPredFlag(i); for( Int j=0; j < 4; j++ ) { seiRegionWisePacking->m_rwpGuardBandType[i*4 + j] = m_pcCfg->getRwpSEIRwpGuardBandType(i*4 + j); } } } } Void SEIEncoder::initSEIFisheyeVideoInfo(SEIFisheyeVideoInfo *seiFisheyeVideoInfo) { assert(m_isInitialized); assert(seiFisheyeVideoInfo != NULL); seiFisheyeVideoInfo->values = m_pcCfg->getFviSEIData(); } template static Void readTokenValue(T &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken, /// token string Bool (*parseFn) (std::istream &, T &) /// parsing function ) { returnedValue=T(); if (failed) { return; } Int c; // Ignore any whitespace while ((c=is.get())!=EOF && isspace(c)); // test for comment mark while (c=='#') { // Ignore to the end of the line while ((c=is.get())!=EOF && (c!=10 && c!=13)); // Ignore any white space at the start of the next line while ((c=is.get())!=EOF && isspace(c)); } // test first character of token failed=(c!=pToken[0]); // test remaining characters of token Int pos; for(pos=1;!failed && pToken[pos]!=0 && is.get()==pToken[pos]; pos++); failed|=(pToken[pos]!=0); // Ignore any whitespace before the ':' while (!failed && (c=is.get())!=EOF && isspace(c)); failed|=(c!=':'); // Now read the value associated with the token: if (!failed) { failed=parseFn(is, returnedValue); } if (failed) { std::cerr << "Unable to read token '" << pToken << "'\n"; } } template static Bool readTokenValueParsing(std::istream &is, T & returnedValue) { is >> returnedValue; Bool failed=!is.good(); if (!failed) { Int c=is.get(); failed=(c!=EOF && !isspace(c)); } return failed; } template <> Bool readTokenValueParsing(std::istream &is, std::string & returnedValue) { Int c; // ignore any initial white space do { c=is.get(); } while (isspace(c) && c!=10 && c!=13 && c!=EOF); Int currentQuoteSymbol=0; Int trailingSpaces=0; while (c!=EOF && c!=0 && c!=10 && c!=13) { if (currentQuoteSymbol==0 && (c=='"' || c=='\'')) { currentQuoteSymbol=c; } else if (c==currentQuoteSymbol) { currentQuoteSymbol=0; } else if (isspace(c) && !currentQuoteSymbol) { trailingSpaces++; } else { if (c=='\\') { c=is.get(); if (c==EOF || c==10 || c==13 || c==0) { return true; // not properly escaped '\' } } if (trailingSpaces) { returnedValue+=string(trailingSpaces, ' '); trailingSpaces=0; } returnedValue+=c; } c=is.get(); } return currentQuoteSymbol!=0; // error if we didn't find a closing quote. } template static Void readTokenValue(T &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken) /// token string { readTokenValue(returnedValue, failed, is, pToken, readTokenValueParsing); } template static Void readTokenValueAndValidate(T &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken, /// token string const T &minInclusive, /// minimum value allowed, inclusive const T &maxInclusive) /// maximum value allowed, inclusive { readTokenValue(returnedValue, failed, is, pToken); if (!failed) { if (returnedValuemaxInclusive) { failed=true; std::cerr << "Value for token " << pToken << " must be in the range " << minInclusive << " to " << maxInclusive << " (inclusive); value read: " << returnedValue << std::endl; } } } // Bool version does not have maximum and minimum values. static Void readTokenValueAndValidate(Bool &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken) /// token string { readTokenValue(returnedValue, failed, is, pToken); } template static Void readTokenValue(std::vector &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken, /// token string const UInt &numValues) /// Num of values to be read in array { returnedValue=std::vector(); if (failed) { return; } Int c; // Ignore any whitespace while ((c=is.get())!=EOF && isspace(c)); // test for comment mark while (c=='#') { // Ignore to the end of the line while ((c=is.get())!=EOF && (c!=10 && c!=13)); // Ignore any white space at the start of the next line while ((c=is.get())!=EOF && isspace(c)); } // test first character of token failed=(c!=pToken[0]); // test remaining characters of token Int pos; for(pos=1;!failed && pToken[pos]!=0 && is.get()==pToken[pos]; pos++); failed|=(pToken[pos]!=0); // Ignore any whitespace before the ':' while (!failed && (c=is.get())!=EOF && isspace(c)); failed|=(c!=':'); // Now read the value associated with the token: for(UInt i = 0; i < numValues; i++) { if (!failed) { is >> returnedValue[i]; failed=!is.good(); if (!failed) { c=is.get(); failed=(c!=EOF && !isspace(c)); } } if (failed) { std::cerr << "Unable to read token '" << pToken << "[" << i << "]'\n"; } } } // Version to read an array template static Void readTokenValueAndValidate(std::vector &returnedValue, /// value returned Bool &failed, /// used and updated std::istream &is, /// stream to read token from const TChar *pToken, /// token string const T &minInclusive, /// minimum value allowed, inclusive const T &maxInclusive, /// maximum value allowed, inclusive const UInt &numValues) { readTokenValue(returnedValue, failed, is, pToken, numValues); if (!failed) { for(UInt i = 0; i < numValues; i++) { if (returnedValue[i]maxInclusive) { failed=true; std::cerr << "Value for token " << pToken << "[" << i << "] must be in the range " << minInclusive << " to " << maxInclusive << " (inclusive); value read: " << returnedValue[i] << std::endl; } } } } Bool SEIEncoder::initSEIColourRemappingInfo(SEIColourRemappingInfo* seiColourRemappingInfo, Int currPOC) // returns true on success, false on failure. { assert (m_isInitialized); assert (seiColourRemappingInfo!=NULL); // reading external Colour Remapping Information SEI message parameters from file if( !m_pcCfg->getColourRemapInfoSEIFileRoot().empty()) { Bool failed=false; // building the CRI file name with poc num in prefix "_poc.txt" std::string colourRemapSEIFileWithPoc(m_pcCfg->getColourRemapInfoSEIFileRoot()); { std::stringstream suffix; suffix << "_" << currPOC << ".txt"; colourRemapSEIFileWithPoc+=suffix.str(); } std::ifstream fic(colourRemapSEIFileWithPoc.c_str()); if (!fic.good() || !fic.is_open()) { std::cerr << "No Colour Remapping Information SEI parameters file " << colourRemapSEIFileWithPoc << " for POC " << currPOC << std::endl; return false; } // TODO: identify and remove duplication with decoder parsing through abstraction. readColourRemapSEI(fic, seiColourRemappingInfo, failed ); if( failed ) { std::cerr << "Error while reading Colour Remapping Information SEI parameters file '" << colourRemapSEIFileWithPoc << "'" << std::endl; exit(EXIT_FAILURE); } } return true; } Void SEIEncoder::readRNSEIWindow(std::istream &fic, RNSEIWindowVec::iterator regionIter, Bool &failed ) { Int regionId; Int offLeft, offRight, offTop, offBottom; fic >> regionId >> offLeft >> offRight >> offTop >> offBottom; (*regionIter).setRegionId(regionId); (*regionIter).setWindow(offLeft, offRight, offTop, offBottom); } Void SEIEncoder::readColourRemapSEI(std::istream &fic, SEIColourRemappingInfo *seiColourRemappingInfo, Bool &failed ) { readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapId, failed, fic, "colour_remap_id", UInt(0), UInt(0x7fffffff) ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapCancelFlag, failed, fic, "colour_remap_cancel_flag" ); if( !seiColourRemappingInfo->m_colourRemapCancelFlag ) { readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapPersistenceFlag, failed, fic, "colour_remap_persistence_flag" ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapVideoSignalInfoPresentFlag, failed, fic, "colour_remap_video_signal_info_present_flag"); if( seiColourRemappingInfo->m_colourRemapVideoSignalInfoPresentFlag ) { readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapFullRangeFlag, failed, fic, "colour_remap_full_range_flag" ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapPrimaries, failed, fic, "colour_remap_primaries", Int(0), Int(255) ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapTransferFunction, failed, fic, "colour_remap_transfer_function", Int(0), Int(255) ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapMatrixCoefficients, failed, fic, "colour_remap_matrix_coefficients", Int(0), Int(255) ); } readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapInputBitDepth, failed, fic, "colour_remap_input_bit_depth", Int(8), Int(16) ); readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapBitDepth, failed, fic, "colour_remap_bit_depth", Int(8), Int(16) ); const Int maximumInputValue = (1 << (((seiColourRemappingInfo->m_colourRemapInputBitDepth + 7) >> 3) << 3)) - 1; const Int maximumRemappedValue = (1 << (((seiColourRemappingInfo->m_colourRemapBitDepth + 7) >> 3) << 3)) - 1; for( Int c=0 ; c<3 ; c++ ) { readTokenValueAndValidate(seiColourRemappingInfo->m_preLutNumValMinus1[c], failed, fic, "pre_lut_num_val_minus1[c]", Int(0), Int(32) ); if( seiColourRemappingInfo->m_preLutNumValMinus1[c]>0 ) { seiColourRemappingInfo->m_preLut[c].resize(seiColourRemappingInfo->m_preLutNumValMinus1[c]+1); for( Int i=0 ; i<=seiColourRemappingInfo->m_preLutNumValMinus1[c] ; i++ ) { readTokenValueAndValidate(seiColourRemappingInfo->m_preLut[c][i].codedValue, failed, fic, "pre_lut_coded_value[c][i]", Int(0), maximumInputValue ); readTokenValueAndValidate(seiColourRemappingInfo->m_preLut[c][i].targetValue, failed, fic, "pre_lut_target_value[c][i]", Int(0), maximumRemappedValue ); } } } readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapMatrixPresentFlag, failed, fic, "colour_remap_matrix_present_flag" ); if( seiColourRemappingInfo->m_colourRemapMatrixPresentFlag ) { readTokenValueAndValidate(seiColourRemappingInfo->m_log2MatrixDenom, failed, fic, "log2_matrix_denom", Int(0), Int(15) ); for( Int c=0 ; c<3 ; c++ ) { for( Int i=0 ; i<3 ; i++ ) { readTokenValueAndValidate(seiColourRemappingInfo->m_colourRemapCoeffs[c][i], failed, fic, "colour_remap_coeffs[c][i]", -32768, 32767 ); } } } for( Int c=0 ; c<3 ; c++ ) { readTokenValueAndValidate(seiColourRemappingInfo->m_postLutNumValMinus1[c], failed, fic, "post_lut_num_val_minus1[c]", Int(0), Int(32) ); if( seiColourRemappingInfo->m_postLutNumValMinus1[c]>0 ) { seiColourRemappingInfo->m_postLut[c].resize(seiColourRemappingInfo->m_postLutNumValMinus1[c]+1); for( Int i=0 ; i<=seiColourRemappingInfo->m_postLutNumValMinus1[c] ; i++ ) { readTokenValueAndValidate(seiColourRemappingInfo->m_postLut[c][i].codedValue, failed, fic, "post_lut_coded_value[c][i]", Int(0), maximumRemappedValue ); readTokenValueAndValidate(seiColourRemappingInfo->m_postLut[c][i].targetValue, failed, fic, "post_lut_target_value[c][i]", Int(0), maximumRemappedValue ); } } } } } Void SEIEncoder::readToneMappingInfoSEI(std::istream &fic, SEIToneMappingInfo *seiToneMappingInfo , Bool &failed ) { readTokenValueAndValidate(seiToneMappingInfo->m_toneMapId, failed, fic, "SEIToneMapId", Int(0), Int(255) ); readTokenValueAndValidate(seiToneMappingInfo->m_toneMapCancelFlag, failed, fic, "SEIToneMapCancelFlag"); readTokenValueAndValidate(seiToneMappingInfo->m_toneMapPersistenceFlag, failed, fic, "SEIToneMapPersistenceFlag"); readTokenValueAndValidate(seiToneMappingInfo->m_codedDataBitDepth, failed, fic, "SEIToneMapCodedDataBitDepth", Int(8), Int(14) ); readTokenValueAndValidate(seiToneMappingInfo->m_targetBitDepth, failed, fic, "SEIToneMapTargetBitDepth", Int(8), Int(14) ); readTokenValueAndValidate(seiToneMappingInfo->m_modelId, failed, fic, "SEIToneMapModelId", Int(0), Int(4) ); readTokenValueAndValidate(seiToneMappingInfo->m_minValue, failed, fic, "SEIToneMapMinValue", Int(0), Int((1<<14)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_maxValue, failed, fic, "SEIToneMapMaxValue", Int(0), Int((1<<14)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_sigmoidMidpoint, failed, fic, "SEIToneMapSigmoidMidpoint", Int(0), Int((1<<14)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_sigmoidWidth, failed, fic, "SEIToneMapSigmoidWidth", Int(0), Int((1<<14)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_startOfCodedInterval, failed, fic, "SEIToneMapStartOfCodedInterval", Int(0), Int((1<<16)-1), UInt(1<m_targetBitDepth) ); readTokenValueAndValidate(seiToneMappingInfo->m_numPivots, failed, fic, "SEIToneMapNumPivots", Int(0), Int((1<<16)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_codedPivotValue, failed, fic, "SEIToneMapCodedPivotValue", Int(0), Int((1<<16)-1), seiToneMappingInfo->m_numPivots ); readTokenValueAndValidate(seiToneMappingInfo->m_targetPivotValue, failed, fic, "SEIToneMapTargetPivotValue", Int(0), Int((1<<16)-1), seiToneMappingInfo->m_numPivots ); readTokenValueAndValidate(seiToneMappingInfo->m_cameraIsoSpeedIdc, failed, fic, "SEIToneMapCameraIsoSpeedIdc", Int(0), Int(255) ); readTokenValueAndValidate(seiToneMappingInfo->m_cameraIsoSpeedValue, failed, fic, "SEIToneMapCameraIsoSpeedValue", Int(0), Int((~0)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_exposureIndexIdc, failed, fic, "SEIToneMapExposureIndexIdc", Int(0), Int(255) ); readTokenValueAndValidate(seiToneMappingInfo->m_exposureIndexValue, failed, fic, "SEIToneMapExposureIndexValue", Int(0), Int((~0)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_exposureCompensationValueSignFlag, failed, fic, "SEIToneMapExposureCompensationValueSignFlag"); readTokenValueAndValidate(seiToneMappingInfo->m_exposureCompensationValueNumerator, failed, fic, "SEIToneMapExposureCompensationValueNumerator", Int(0), Int((1<<16)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_exposureCompensationValueDenomIdc, failed, fic, "SEIToneMapExposureCompensationValueDenomIdc", Int(0), Int((1<<16)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_refScreenLuminanceWhite, failed, fic, "SEIToneMapRefScreenLuminanceWhite", Int(0), Int(10000) ); readTokenValueAndValidate(seiToneMappingInfo->m_extendedRangeWhiteLevel, failed, fic, "SEIToneMapExtendedRangeWhiteLevel", Int(100), Int(10000) ); readTokenValueAndValidate(seiToneMappingInfo->m_nominalBlackLevelLumaCodeValue, failed, fic, "SEIToneMapNominalBlackLevelLumaCodeValue", Int(0), Int((1<<16)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue, failed, fic, "SEIToneMapNominalWhiteLevelLumaCodeValue", Int(0), Int((1<<16)-1) ); readTokenValueAndValidate(seiToneMappingInfo->m_extendedWhiteLevelLumaCodeValue, failed, fic, "SEIToneMapExtendedWhiteLevelLumaCodeValue", Int(0), Int((1<<16)-1) ); } Void SEIEncoder::readChromaResamplingFilterHintSEI(std::istream &fic, SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint, Bool &failed ) { Int horFilType, verFilType; readTokenValueAndValidate(horFilType, failed, fic, "SEIChromaResamplingHorizontalFilterType", Int(0), Int(2) ); readTokenValueAndValidate(verFilType, failed, fic, "SEIChromaResamplingVerticalFilterType", Int(0), Int(2) ); if(horFilType == 1 || verFilType == 1) { cout << "Encoder support needed for scanning additional syntax elements of chroma resampling filter hint SEI message.\n"; cout << "Addn. code needed in readChromaResamplingFilterHintSEI() and initSEIChromaResamplingFilterHint().\n"; exit(1); } initSEIChromaResamplingFilterHint(seiChromaResamplingFilterHint, horFilType, verFilType); } Void SEIEncoder::readKneeFunctionInfoSEI(std::istream &fic, SEIKneeFunctionInfo *seiKneeFunctionInfo, Bool &failed ) { readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeId, failed, fic, "SEIKneeFunctionId", Int(0), Int(255)); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeCancelFlag, failed, fic, "SEIKneeFunctionCancelFlag" ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneePersistenceFlag, failed, fic, "SEIKneeFunctionPersistenceFlag" ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeInputDrange, failed, fic, "SEIKneeFunctionInputDrange", Int(0), Int(1000) ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeInputDispLuminance, failed, fic, "SEIKneeFunctionInputDispLuminance", Int(0), Int(10000) ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeOutputDrange, failed, fic, "SEIKneeFunctionOutputDrange", Int(0), Int(1000) ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeOutputDispLuminance, failed, fic, "SEIKneeFunctionOutputDispLuminance",Int(0), Int(10000) ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeNumKneePointsMinus1, failed, fic, "SEIKneeFunctionNumKneePointsMinus1",Int(0), Int(998) ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeInputKneePoint, failed, fic, "SEIKneeFunctionInputKneePointValue",Int(0), Int(1000), seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1 ); readTokenValueAndValidate(seiKneeFunctionInfo->m_kneeOutputKneePoint, failed, fic, "SEIKneeFunctionInputKneePointValue",Int(0), Int(1000), seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1 ); } Void SEIEncoder::readContentColourVolumeSEI(std::istream &fic, SEIContentColourVolume *seiContentColourVolume, Bool &failed ) { Double dCode, primaries[2][MAX_NUM_COMPONENT]; readTokenValueAndValidate(seiContentColourVolume->m_ccvCancelFlag, failed, fic, "SEICCVCancelFlag" ); readTokenValueAndValidate(seiContentColourVolume->m_ccvPersistenceFlag, failed, fic, "SEICCVPersistenceFlag" ); readTokenValueAndValidate(seiContentColourVolume->m_ccvPrimariesPresentFlag, failed, fic, "SEICCVPrimariesPresent" ); readTokenValueAndValidate(primaries[0][0], failed, fic, "m_ccvSEIPrimariesX0", Double(-100), Double(100)); readTokenValueAndValidate(primaries[1][1], failed, fic, "m_ccvSEIPrimariesY0", Double(-100), Double(100)); readTokenValueAndValidate(primaries[0][2], failed, fic, "m_ccvSEIPrimariesX1", Double(-100), Double(100)); readTokenValueAndValidate(primaries[1][0], failed, fic, "m_ccvSEIPrimariesY1", Double(-100), Double(100)); readTokenValueAndValidate(primaries[0][1], failed, fic, "m_ccvSEIPrimariesX2", Double(-100), Double(100)); readTokenValueAndValidate(primaries[1][2], failed, fic, "m_ccvSEIPrimariesY2", Double(-100), Double(100)); if(seiContentColourVolume->m_ccvPrimariesPresentFlag) { for (Int i = 0; i < MAX_NUM_COMPONENT; i++) { seiContentColourVolume->m_ccvPrimariesX[i] = (Int) (50000.0 * primaries[0][i]); seiContentColourVolume->m_ccvPrimariesY[i] = (Int) (50000.0 * primaries[1][i]); } } readTokenValueAndValidate(seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag, failed, fic, "SEICCVMinLuminanceValuePresent" ); readTokenValueAndValidate(dCode, failed, fic, "SEICCVMinLuminanceValue", Double(0), Double(429.4967295)); if(seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag) { seiContentColourVolume->m_ccvMinLuminanceValue = (Int) (10000000 * dCode); } readTokenValueAndValidate(seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag, failed, fic, "SEICCVMaxLuminanceValuePresent" ); readTokenValueAndValidate(dCode, failed, fic, "SEICCVMaxLuminanceValue", Double(0), Double(429.4967295)); if(seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag) { seiContentColourVolume->m_ccvMaxLuminanceValue = (Int) (10000000 * dCode); } readTokenValueAndValidate(seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag, failed, fic, "SEICCVAvgLuminanceValuePresent" ); readTokenValueAndValidate(dCode, failed, fic, "SEICCVAvgLuminanceValue", Double(0), Double(429.4967295)); if(seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag) { seiContentColourVolume->m_ccvAvgLuminanceValue = (Int) (10000000 * dCode); } } Bool SEIEncoder::initSEIRegionalNesting(SEIRegionalNesting* seiRegionalNesting, Int currPOC) // returns true on success, false on failure. { assert (m_isInitialized); assert (seiRegionalNesting!=NULL); Int numRegions; RNSEIWindowVec regions; // reading external regional nesting SEI message parameters from file if( !m_pcCfg->getRegionalNestingSEIFileRoot().empty()) { Bool failed=false; // building the regional nesting file name with poc num in prefix "_poc.txt" std::string regionalNestingSEIFileWithPoc(m_pcCfg->getRegionalNestingSEIFileRoot()); { std::stringstream suffix; suffix << "_" << currPOC << ".txt"; regionalNestingSEIFileWithPoc+=suffix.str(); } std::ifstream fic(regionalNestingSEIFileWithPoc.c_str()); if (!fic.good() || !fic.is_open()) { std::cerr << "No Regional Nesting Information SEI parameters file " << regionalNestingSEIFileWithPoc << " for POC " << currPOC << std::endl; return false; } Int payloadType, numSEIs; readTokenValueAndValidate( numSEIs, failed, fic, "num_seis", 0, 255 ); // Loop through each region - ID - SEI for(Int i = 0; i < numSEIs; i++) { RegionalSEI *regSEI = NULL; // Parse num region readTokenValueAndValidate( numRegions, failed, fic, "num_regions", 0, 255 ); regions.resize(numRegions); RNSEIWindowVec::iterator regionIter; for(regionIter = regions.begin(); regionIter != regions.end(); regionIter++) { readRNSEIWindow(fic, regionIter, failed); } // Parse payloadType readTokenValueAndValidate( payloadType, failed, fic, "payloadType", 0, 255 ); if(!RegionalSEI::checkRegionalNestedSEIPayloadType(SEI::PayloadType(payloadType))) { cout << "PayloadType " << payloadType << " not supported in regional nesting SEI message. Exiting.\n"; exit(1); } // Parse SEI switch(SEI::PayloadType(payloadType)) { case SEI::FILM_GRAIN_CHARACTERISTICS: // TBD - no encoder support case SEI::POST_FILTER_HINT: // TBD - no encoder support case SEI::USER_DATA_REGISTERED_ITU_T_T35: // TBD: Support for user-data SEI to be added case SEI::USER_DATA_UNREGISTERED: // TBD: Support for user-data SEI to be added { cout << "Encoder support for " << SEI::getSEIMessageString(SEI::PayloadType(payloadType)) << " nested in regional nesting SEI message needs to be added.\n"; exit(1); } case SEI::TONE_MAPPING_INFO: { SEIToneMappingInfo *seiToneMappingInfo = new SEIToneMappingInfo; readToneMappingInfoSEI(fic, seiToneMappingInfo, failed); regSEI = new RegionalSEI(seiToneMappingInfo, regions); break; } case SEI::CHROMA_RESAMPLING_FILTER_HINT: { SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint = new SEIChromaResamplingFilterHint; readChromaResamplingFilterHintSEI(fic, seiChromaResamplingFilterHint, failed); regSEI = new RegionalSEI(seiChromaResamplingFilterHint, regions); break; } case SEI::KNEE_FUNCTION_INFO: { SEIKneeFunctionInfo *seiKneeFunctionInfo = new SEIKneeFunctionInfo; readKneeFunctionInfoSEI(fic, seiKneeFunctionInfo, failed); regSEI = new RegionalSEI(seiKneeFunctionInfo, regions); break; } case SEI::COLOUR_REMAPPING_INFO: { SEIColourRemappingInfo *seiColourRemappingInfo = new SEIColourRemappingInfo; readColourRemapSEI(fic, seiColourRemappingInfo, failed); regSEI = new RegionalSEI(seiColourRemappingInfo, regions); break; } case SEI::CONTENT_COLOUR_VOLUME: { SEIContentColourVolume *seiContentColourVolume = new SEIContentColourVolume; readContentColourVolumeSEI(fic, seiContentColourVolume, failed); regSEI = new RegionalSEI(seiContentColourVolume, regions); break; } default: cout << "Unable to read the payloadType " << payloadType << " in " << regionalNestingSEIFileWithPoc << std::endl; exit(1); } if( failed ) { std::cerr << "Error while reading regional nesting SEI parameters file '" << regionalNestingSEIFileWithPoc << "'" << std::endl; exit(EXIT_FAILURE); } // Add to SEI if(regSEI) { seiRegionalNesting->addRegionalSEI(regSEI); delete regSEI; } else { // Error - SEI should've been read. } } } return true; } Void SEIEncoder::readAnnotatedRegionSEI(std::istream &fic, SEIAnnotatedRegions *seiAnnoRegion, Bool &failed) { readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_cancelFlag, failed, fic, "SEIArCancelFlag"); if (!seiAnnoRegion->m_hdr.m_cancelFlag) { readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_notOptimizedForViewingFlag, failed, fic, "SEIArNotOptForViewingFlag"); readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_trueMotionFlag, failed, fic, "SEIArTrueMotionFlag"); readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_occludedObjectFlag, failed, fic, "SEIArOccludedObjsFlag"); readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_partialObjectFlagPresentFlag, failed, fic, "SEIArPartialObjsFlagPresentFlag"); readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_objectLabelPresentFlag, failed, fic, "SEIArObjLabelPresentFlag"); readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_objectConfidenceInfoPresentFlag, failed, fic, "SEIArObjConfInfoPresentFlag"); if (seiAnnoRegion->m_hdr.m_objectConfidenceInfoPresentFlag) { readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_objectConfidenceLength, failed, fic, "SEIArObjDetConfLength", UInt(0), UInt(255)); } if (seiAnnoRegion->m_hdr.m_objectLabelPresentFlag) { readTokenValueAndValidate(seiAnnoRegion->m_hdr.m_objectLabelLanguagePresentFlag, failed, fic, "SEIArObjLabelLangPresentFlag"); if (seiAnnoRegion->m_hdr.m_objectLabelLanguagePresentFlag) { readTokenValue(seiAnnoRegion->m_hdr.m_annotatedRegionsObjectLabelLang, failed, fic, "SEIArLabelLanguage"); } UInt numLabelUpdates=0; readTokenValueAndValidate(numLabelUpdates, failed, fic, "SEIArNumLabelUpdates", UInt(0), UInt(255)); seiAnnoRegion->m_annotatedLabels.resize(numLabelUpdates); for (auto it=seiAnnoRegion->m_annotatedLabels.begin(); it!=seiAnnoRegion->m_annotatedLabels.end(); it++) { SEIAnnotatedRegions::AnnotatedRegionLabel &ar=it->second; readTokenValueAndValidate(it->first, failed, fic, "SEIArLabelIdc[c]", UInt(0), UInt(255)); bool cancelFlag; readTokenValueAndValidate(cancelFlag, failed, fic, "SEIArLabelCancelFlag[c]"); ar.labelValid=!cancelFlag; if (ar.labelValid) { readTokenValue(ar.label, failed, fic, "SEIArLabel[c]"); } } } UInt numObjectUpdates=0; readTokenValueAndValidate(numObjectUpdates, failed, fic, "SEIArNumObjUpdates", UInt(0), UInt(255)); seiAnnoRegion->m_annotatedRegions.resize(numObjectUpdates); for (auto it=seiAnnoRegion->m_annotatedRegions.begin(); it!=seiAnnoRegion->m_annotatedRegions.end(); it++) { SEIAnnotatedRegions::AnnotatedRegionObject &ar = it->second; readTokenValueAndValidate(it->first, failed, fic, "SEIArObjIdx[c]", UInt(0), UInt(255)); readTokenValueAndValidate(ar.objectCancelFlag, failed, fic, "SEIArObjCancelFlag[c]"); ar.objectLabelValid=false; ar.boundingBoxValid=false; if (!ar.objectCancelFlag) { if (seiAnnoRegion->m_hdr.m_objectLabelPresentFlag) { readTokenValueAndValidate(ar.objectLabelValid, failed, fic, "SEIArObjLabelUpdateFlag[c]"); if (ar.objectLabelValid) { readTokenValueAndValidate(ar.objLabelIdx, failed, fic, "SEIArObjectLabelIdc[c]", UInt(0), UInt(255)); } } readTokenValueAndValidate(ar.boundingBoxValid, failed, fic, "SEIArBoundBoxUpdateFlag[c]"); if (ar.boundingBoxValid) { readTokenValueAndValidate(ar.boundingBoxCancelFlag, failed, fic, "SEIArBoundBoxCancelFlag[c]"); if (!ar.boundingBoxCancelFlag) { readTokenValueAndValidate(ar.boundingBoxTop, failed, fic, "SEIArObjTop[c]", UInt(0), UInt(0x7fffffff)); readTokenValueAndValidate(ar.boundingBoxLeft, failed, fic, "SEIArObjLeft[c]", UInt(0), UInt(0x7fffffff)); readTokenValueAndValidate(ar.boundingBoxWidth, failed, fic, "SEIArObjWidth[c]", UInt(0), UInt(0x7fffffff)); readTokenValueAndValidate(ar.boundingBoxHeight, failed, fic, "SEIArObjHeight[c]", UInt(0), UInt(0x7fffffff)); if (seiAnnoRegion->m_hdr.m_partialObjectFlagPresentFlag) { readTokenValueAndValidate(ar.partialObjectFlag, failed, fic, "SEIArObjPartUpdateFlag[c]"); } if (seiAnnoRegion->m_hdr.m_objectConfidenceInfoPresentFlag) { readTokenValueAndValidate(ar.objectConfidence, failed, fic, "SEIArObjDetConf[c]", UInt(0), UInt(1<m_hdr.m_objectConfidenceLength)-1); } } if (seiAnnoRegion->m_hdr.m_objectConfidenceInfoPresentFlag) { readTokenValueAndValidate(ar.objectConfidence, failed, fic, "SEIArObjDetConf[c]", UInt(0), UInt(1<m_hdr.m_objectConfidenceLength)-1); } } #if JVET_T0050_ANNOTATED_REGIONS_SEI //Compare with existing attributes to decide whether it's a static object //First check whether it's an existing object (or) new object auto destIt = m_pcCfg->m_arObjects.find(it->first); //New object if (destIt == m_pcCfg->m_arObjects.end()) { //New object arrived, needs to be appended to the map of tracked objects m_pcCfg->m_arObjects[it->first] = ar; } //Existing object else { // Size remains the same if(m_pcCfg->m_arObjects[it->first].boundingBoxWidth == ar.boundingBoxWidth && m_pcCfg->m_arObjects[it->first].boundingBoxHeight == ar.boundingBoxHeight) { if(m_pcCfg->m_arObjects[it->first].boundingBoxTop == ar.boundingBoxTop && m_pcCfg->m_arObjects[it->first].boundingBoxLeft == ar.boundingBoxLeft) { ar.boundingBoxValid = 0; } } } #endif } #if JVET_T0050_ANNOTATED_REGIONS_SEI else { //Object has been marked for deletion auto destIt = m_pcCfg->m_arObjects.find(it->first); if (destIt != m_pcCfg->m_arObjects.end()) { m_pcCfg->m_arObjects.erase(destIt); } } #endif } } #if JVET_T0050_ANNOTATED_REGIONS_SEI else { seiAnnoRegion->m_annotatedRegions.clear(); seiAnnoRegion->m_annotatedLabels.clear(); m_pcCfg->m_arObjects.clear(); } #endif } Bool SEIEncoder::initSEIAnnotatedRegions(SEIAnnotatedRegions* SEIAnnoReg, Int currPOC) { assert(m_isInitialized); assert(SEIAnnoReg != NULL); // reading external Colour Remapping Information SEI message parameters from file if (!m_pcCfg->getAnnotatedRegionSEIFileRoot().empty()) { Bool failed = false; // building the annotated regions file name with poc num in prefix "_poc.txt" std::string AnnoRegionSEIFileWithPoc(m_pcCfg->getAnnotatedRegionSEIFileRoot()); { std::stringstream suffix; suffix << "_" << currPOC << ".txt"; AnnoRegionSEIFileWithPoc += suffix.str(); } std::ifstream fic(AnnoRegionSEIFileWithPoc.c_str()); if (!fic.good() || !fic.is_open()) { std::cerr << "No Annotated Regions SEI parameters file " << AnnoRegionSEIFileWithPoc << " for POC " << currPOC << std::endl; return false; } //Read annotated region SEI parameters from the cfg file readAnnotatedRegionSEI(fic, SEIAnnoReg, failed); if (failed) { std::cerr << "Error while reading Annotated Regions SEI parameters file '" << AnnoRegionSEIFileWithPoc << "'" << std::endl; exit(EXIT_FAILURE); } } return true; } Void SEIEncoder::initSEIChromaResamplingFilterHint(SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint, Int iHorFilterIndex, Int iVerFilterIndex) { assert (m_isInitialized); assert (seiChromaResamplingFilterHint!=NULL); seiChromaResamplingFilterHint->m_verChromaFilterIdc = iVerFilterIndex; seiChromaResamplingFilterHint->m_horChromaFilterIdc = iHorFilterIndex; seiChromaResamplingFilterHint->m_verFilteringFieldProcessingFlag = 1; seiChromaResamplingFilterHint->m_targetFormatIdc = 3; seiChromaResamplingFilterHint->m_perfectReconstructionFlag = false; // this creates some example filter values, if explicit filter definition is selected if (seiChromaResamplingFilterHint->m_verChromaFilterIdc == 1) { const Int numVerticalFilters = 3; const Int verTapLengthMinus1[] = {5,3,3}; seiChromaResamplingFilterHint->m_verFilterCoeff.resize(numVerticalFilters); for(Int i = 0; i < numVerticalFilters; i ++) { seiChromaResamplingFilterHint->m_verFilterCoeff[i].resize(verTapLengthMinus1[i]+1); } // Note: C++11 -> seiChromaResamplingFilterHint->m_verFilterCoeff[0] = {-3,13,31,23,3,-3}; seiChromaResamplingFilterHint->m_verFilterCoeff[0][0] = -3; seiChromaResamplingFilterHint->m_verFilterCoeff[0][1] = 13; seiChromaResamplingFilterHint->m_verFilterCoeff[0][2] = 31; seiChromaResamplingFilterHint->m_verFilterCoeff[0][3] = 23; seiChromaResamplingFilterHint->m_verFilterCoeff[0][4] = 3; seiChromaResamplingFilterHint->m_verFilterCoeff[0][5] = -3; seiChromaResamplingFilterHint->m_verFilterCoeff[1][0] = -1; seiChromaResamplingFilterHint->m_verFilterCoeff[1][1] = 25; seiChromaResamplingFilterHint->m_verFilterCoeff[1][2] = 247; seiChromaResamplingFilterHint->m_verFilterCoeff[1][3] = -15; seiChromaResamplingFilterHint->m_verFilterCoeff[2][0] = -20; seiChromaResamplingFilterHint->m_verFilterCoeff[2][1] = 186; seiChromaResamplingFilterHint->m_verFilterCoeff[2][2] = 100; seiChromaResamplingFilterHint->m_verFilterCoeff[2][3] = -10; } else { seiChromaResamplingFilterHint->m_verFilterCoeff.resize(0); } if (seiChromaResamplingFilterHint->m_horChromaFilterIdc == 1) { Int const numHorizontalFilters = 1; const Int horTapLengthMinus1[] = {3}; seiChromaResamplingFilterHint->m_horFilterCoeff.resize(numHorizontalFilters); for(Int i = 0; i < numHorizontalFilters; i ++) { seiChromaResamplingFilterHint->m_horFilterCoeff[i].resize(horTapLengthMinus1[i]+1); } seiChromaResamplingFilterHint->m_horFilterCoeff[0][0] = 1; seiChromaResamplingFilterHint->m_horFilterCoeff[0][1] = 6; seiChromaResamplingFilterHint->m_horFilterCoeff[0][2] = 1; } else { seiChromaResamplingFilterHint->m_horFilterCoeff.resize(0); } } Void SEIEncoder::initSEITimeCode(SEITimeCode *seiTimeCode) { assert (m_isInitialized); assert (seiTimeCode!=NULL); // Set data as per command line options seiTimeCode->numClockTs = m_pcCfg->getNumberOfTimesets(); for(Int i = 0; i < seiTimeCode->numClockTs; i++) { seiTimeCode->timeSetArray[i] = m_pcCfg->getTimeSet(i); } } Void SEIEncoder::initSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics *seiAltTransCharacteristics) { assert (m_isInitialized); assert (seiAltTransCharacteristics!=NULL); // Set SEI message parameters read from command line options seiAltTransCharacteristics->m_preferredTransferCharacteristics = m_pcCfg->getSEIPreferredTransferCharacteristics(); } Void SEIEncoder::initSEIGreenMetadataInfo(SEIGreenMetadataInfo *seiGreenMetadataInfo, UInt u) { assert (m_isInitialized); assert (seiGreenMetadataInfo!=NULL); seiGreenMetadataInfo->m_greenMetadataType = m_pcCfg->getSEIGreenMetadataType(); seiGreenMetadataInfo->m_xsdMetricType = m_pcCfg->getSEIXSDMetricType(); seiGreenMetadataInfo->m_xsdMetricValue = u; } #if JCTVC_AD0021_SEI_MANIFEST Void SEIEncoder::initSEISEIManifest(SEIManifest* seiSeiManifest, const SEIMessages& seiMessages) { assert(m_isInitialized); assert(seiSeiManifest != NULL); seiSeiManifest->m_manifestNumSeiMsgTypes = 0; for (auto& it : seiMessages) { seiSeiManifest->m_manifestNumSeiMsgTypes += 1; auto tempPayloadType = it->payloadType(); seiSeiManifest->m_manifestSeiPayloadType.push_back(tempPayloadType); auto description = seiSeiManifest->getSEIMessageDescription(tempPayloadType); seiSeiManifest->m_manifestSeiDescription.push_back(description); } } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Void SEIEncoder::initSEISEIPrefixIndication(SEIPrefixIndication* seiSeiPrefixIndications, const SEI* sei) { assert(m_isInitialized); assert(seiSeiPrefixIndications != NULL); seiSeiPrefixIndications->m_prefixSeiPayloadType = sei->payloadType(); seiSeiPrefixIndications->m_numSeiPrefixIndicationsMinus1 = seiSeiPrefixIndications->getNumsOfSeiPrefixIndications(sei) - 1; seiSeiPrefixIndications->m_payload = sei; } #endif //! \} HM-HM-18.0/source/Lib/TLibEncoder/SEIEncoder.h000066400000000000000000000143371442026013100205020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifndef __SEIENCODER__ #define __SEIENCODER__ #include "TLibCommon/SEI.h" // forward declarations class TEncCfg; class TEncTop; class TEncGOP; //! Initializes different SEI message types based on given encoder configuration parameters class SEIEncoder { public: SEIEncoder() :m_pcCfg(NULL) ,m_pcEncTop(NULL) ,m_pcEncGOP(NULL) ,m_tl0Idx(0) ,m_rapIdx(0) ,m_isInitialized(false) {}; virtual ~SEIEncoder(){}; Void init(TEncCfg* encCfg, TEncTop *encTop, TEncGOP *encGOP) { m_pcCfg = encCfg; m_pcEncGOP = encGOP; m_pcEncTop = encTop; m_isInitialized = true; }; // leading SEIs Void initSEIActiveParameterSets (SEIActiveParameterSets *sei, const TComVPS *vps, const TComSPS *sps); Void initSEIFramePacking(SEIFramePacking *sei, Int currPicNum); Void initSEIDisplayOrientation(SEIDisplayOrientation *sei); Void initSEIToneMappingInfo(SEIToneMappingInfo *sei); Void initSEISOPDescription(SEISOPDescription *sei, TComSlice *slice, Int picInGOP, Int lastIdr, Int currGOPSize); Void initSEIBufferingPeriod(SEIBufferingPeriod *sei, TComSlice *slice); Void initSEIScalableNesting(SEIScalableNesting *sei, SEIMessages &nestedSEIs); Void initSEIRecoveryPoint(SEIRecoveryPoint *sei, TComSlice *slice); Void initSEISegmentedRectFramePacking(SEISegmentedRectFramePacking *sei); Void initSEITempMotionConstrainedTileSets (SEITempMotionConstrainedTileSets *sei, const TComPPS *pps); #if MCTS_EXTRACTION Void initSEIMCTSExtractionInfo(SEIMCTSExtractionInfoSet *sei, const TComVPS *vps, const TComSPS *sps, const TComPPS *pps); #endif Void initSEIKneeFunctionInfo(SEIKneeFunctionInfo *sei); Void initSEIContentColourVolume(SEIContentColourVolume *sei); #if SHUTTER_INTERVAL_SEI_MESSAGE Void initSEIShutterIntervalInfo(SEIShutterIntervalInfo *sei); #endif #if SEI_ENCODER_CONTROL Void initSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics *sei); Void initSEIContentLightLevel(SEIContentLightLevelInfo *sei); Void initSEIAmbientViewingEnvironment(SEIAmbientViewingEnvironment *sei); #endif Void initSEIErp(SEIEquirectangularProjection *sei); Void initSEISphereRotation(SEISphereRotation *sei); Void initSEIOmniViewport(SEIOmniViewport *sei); Void initSEICubemapProjection(SEICubemapProjection *sei); Void initSEIRegionWisePacking(SEIRegionWisePacking *sei); Void initSEIFisheyeVideoInfo(SEIFisheyeVideoInfo *sei); Void initSEIChromaResamplingFilterHint(SEIChromaResamplingFilterHint *sei, Int iHorFilterIndex, Int iVerFilterIndex); Void initSEITimeCode(SEITimeCode *sei); Bool initSEIColourRemappingInfo(SEIColourRemappingInfo *sei, Int currPOC); // returns true on success, false on failure. Void initSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics *sei); Void readToneMappingInfoSEI(std::istream &fic, SEIToneMappingInfo *seiToneMappingInfo , Bool &failed ); Void readChromaResamplingFilterHintSEI(std::istream &fic, SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint, Bool &failed ); Void readKneeFunctionInfoSEI(std::istream &fic, SEIKneeFunctionInfo *seiKneeFunctionInfo, Bool &failed ); Void readColourRemapSEI(std::istream &fic, SEIColourRemappingInfo *seiColorRemappingInfo, Bool &failed ); Void readContentColourVolumeSEI(std::istream &fic, SEIContentColourVolume *seiContentColourVolume, Bool &failed ); Bool initSEIRegionalNesting(SEIRegionalNesting *sei, Int currPOC); // returns true on success, false on failure. Void readRNSEIWindow(std::istream &fic, RNSEIWindowVec::iterator regionIter, Bool &failed ); Bool initSEIAnnotatedRegions(SEIAnnotatedRegions *sei, Int currPOC); Void readAnnotatedRegionSEI(std::istream &fic, SEIAnnotatedRegions *seiAnnoRegion, Bool &failed); #if JCTVC_AD0021_SEI_MANIFEST Void initSEISEIManifest(SEIManifest* seiSeiManifest, const SEIMessages& seiMessage); #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Void initSEISEIPrefixIndication(SEIPrefixIndication* seiSeiPrefixIndications, const SEI* sei); #endif // trailing SEIs Void initDecodedPictureHashSEI(SEIDecodedPictureHash *sei, TComPic *pcPic, std::string &rHashString, const BitDepths &bitDepths); Void initTemporalLevel0IndexSEI(SEITemporalLevel0Index *sei, TComSlice *slice); Void initSEIGreenMetadataInfo(SEIGreenMetadataInfo *sei, UInt u); private: TEncCfg* m_pcCfg; TEncTop* m_pcEncTop; TEncGOP* m_pcEncGOP; // for temporal level 0 index SEI UInt m_tl0Idx; UInt m_rapIdx; Bool m_isInitialized; }; //! \} #endif // __SEIENCODER__ HM-HM-18.0/source/Lib/TLibEncoder/SEIwrite.cpp000066400000000000000000002070211442026013100206020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "TLibCommon/TComBitCounter.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/SEI.h" #include "TLibCommon/TComSlice.h" #include "TLibCommon/TComPicYuv.h" #include "SEIwrite.h" //! \ingroup TLibEncoder //! \{ #if ENC_DEC_TRACE Void xTraceSEIHeader() { fprintf( g_hTrace, "=========== SEI message ===========\n"); } Void xTraceSEIMessageType(SEI::PayloadType payloadType) { fprintf( g_hTrace, "=========== %s SEI message ===========\n", SEI::getSEIMessageString(payloadType)); } #endif Void SEIWriter::xWriteSEIpayloadData(TComBitIf& bs, const SEI& sei, const TComSPS *sps #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx #endif ) { switch (sei.payloadType()) { case SEI::BUFFERING_PERIOD: xWriteSEIBufferingPeriod(*static_cast(&sei), sps); break; case SEI::PICTURE_TIMING: xWriteSEIPictureTiming(*static_cast(&sei), sps); break; case SEI::PAN_SCAN_RECT: xWriteSEIPanScanRect(*static_cast(&sei)); break; case SEI::FILLER_PAYLOAD: xWriteSEIFillerPayload(*static_cast(&sei)); break; case SEI::USER_DATA_REGISTERED_ITU_T_T35: xWriteSEIUserDataRegistered(*static_cast(&sei)); break; case SEI::USER_DATA_UNREGISTERED: xWriteSEIUserDataUnregistered(*static_cast(&sei)); break; case SEI::RECOVERY_POINT: xWriteSEIRecoveryPoint(*static_cast(&sei)); break; case SEI::SCENE_INFO: xWriteSEISceneInfo(*static_cast(&sei)); break; case SEI::PICTURE_SNAPSHOT: xWriteSEIPictureSnapshot(*static_cast(&sei)); break; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_START: xWriteSEIProgressiveRefinementSegmentStart(*static_cast(&sei)); break; case SEI::PROGRESSIVE_REFINEMENT_SEGMENT_END: xWriteSEIProgressiveRefinementSegmentEnd(*static_cast(&sei)); break; case SEI::FILM_GRAIN_CHARACTERISTICS: xWriteSEIFilmGrainCharacteristics(*static_cast(&sei)); break; case SEI::POST_FILTER_HINT: xWriteSEIPostFilterHint(*static_cast(&sei), sps); break; case SEI::TONE_MAPPING_INFO: xWriteSEIToneMappingInfo(*static_cast(&sei)); break; case SEI::FRAME_PACKING: xWriteSEIFramePacking(*static_cast(&sei) #if JCTVC_AD0021_SEI_PREFIX_INDICATION , SEIPrefixIndicationIdx #endif ); break; case SEI::DISPLAY_ORIENTATION: xWriteSEIDisplayOrientation(*static_cast(&sei)); break; case SEI::GREEN_METADATA: xWriteSEIGreenMetadataInfo(*static_cast(&sei)); break; case SEI::SOP_DESCRIPTION: xWriteSEISOPDescription(*static_cast(&sei)); break; case SEI::ACTIVE_PARAMETER_SETS: xWriteSEIActiveParameterSets(*static_cast(& sei)); break; case SEI::DECODING_UNIT_INFO: xWriteSEIDecodingUnitInfo(*static_cast(& sei), sps); break; case SEI::TEMPORAL_LEVEL0_INDEX: xWriteSEITemporalLevel0Index(*static_cast(&sei)); break; case SEI::DECODED_PICTURE_HASH: xWriteSEIDecodedPictureHash(*static_cast(&sei)); break; case SEI::SCALABLE_NESTING: xWriteSEIScalableNesting(bs, *static_cast(&sei), sps); break; case SEI::REGION_REFRESH_INFO: xWriteSEIRegionRefreshInfo(*static_cast(&sei)); break; case SEI::NO_DISPLAY: xWriteSEINoDisplay(*static_cast(&sei)); break; case SEI::TIME_CODE: xWriteSEITimeCode(*static_cast(&sei)); break; case SEI::MASTERING_DISPLAY_COLOUR_VOLUME: xWriteSEIMasteringDisplayColourVolume(*static_cast(&sei)); break; case SEI::SEGM_RECT_FRAME_PACKING: xWriteSEISegmentedRectFramePacking(*static_cast(&sei)); break; case SEI::TEMP_MOTION_CONSTRAINED_TILE_SETS: xWriteSEITempMotionConstrainedTileSets(*static_cast(&sei)); break; #if MCTS_EXTRACTION case SEI::MCTS_EXTRACTION_INFO_SET: xWriteSEIMCTSExtractionInfoSet(*static_cast(&sei)); break; #endif case SEI::CHROMA_RESAMPLING_FILTER_HINT: xWriteSEIChromaResamplingFilterHint(*static_cast(&sei)); break; case SEI::KNEE_FUNCTION_INFO: xWriteSEIKneeFunctionInfo(*static_cast(&sei)); break; case SEI::COLOUR_REMAPPING_INFO: xWriteSEIColourRemappingInfo(*static_cast(&sei)); break; case SEI::DEINTERLACE_FIELD_IDENTIFICATION: xWriteSEIDeinterlaceFieldIdentification(*static_cast(&sei)); break; case SEI::CONTENT_LIGHT_LEVEL_INFO: xWriteSEIContentLightLevelInfo(*static_cast(&sei)); break; case SEI::DEPENDENT_RAP_INDICATION: xWriteSEIDependentRAPIndication(*static_cast(&sei)); break; case SEI::CODED_REGION_COMPLETION: xWriteSEICodedRegionCompletion(*static_cast(&sei)); break; case SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS: xWriteSEIAlternativeTransferCharacteristics(*static_cast(&sei)); break; case SEI::AMBIENT_VIEWING_ENVIRONMENT: xWriteSEIAmbientViewingEnvironment(*static_cast(&sei)); break; case SEI::CONTENT_COLOUR_VOLUME: xWriteSEIContentColourVolume(*static_cast(&sei)); break; case SEI::EQUIRECTANGULAR_PROJECTION: xWriteSEIEquirectangularProjection(*static_cast(&sei) #if JCTVC_AD0021_SEI_PREFIX_INDICATION , SEIPrefixIndicationIdx #endif ); break; case SEI::SPHERE_ROTATION: xWriteSEISphereRotation(*static_cast(&sei) #if JCTVC_AD0021_SEI_PREFIX_INDICATION , SEIPrefixIndicationIdx #endif ); break; case SEI::OMNI_VIEWPORT: xWriteSEIOmniViewport(*static_cast(&sei)); break; case SEI::CUBEMAP_PROJECTION: xWriteSEICubemapProjection(*static_cast(&sei)); break; case SEI::REGION_WISE_PACKING: xWriteSEIRegionWisePacking(*static_cast(&sei) #if JCTVC_AD0021_SEI_PREFIX_INDICATION , SEIPrefixIndicationIdx #endif ); break; case SEI::FISHEYE_VIDEO_INFO: xWriteSEIFisheyeVideoInfo(*static_cast(&sei)); break; case SEI::REGIONAL_NESTING: xWriteSEIRegionalNesting(bs, *static_cast(&sei), sps); break; case SEI::ANNOTATED_REGIONS: xWriteSEIAnnotatedRegions(*static_cast(&sei), sps); break; #if SHUTTER_INTERVAL_SEI_MESSAGE case SEI::SHUTTER_INTERVAL_INFO: xWriteSEIShutterInterval(*static_cast(&sei)); break; #endif #if JCTVC_AD0021_SEI_MANIFEST case SEI::SEI_MANIFEST: xWriteSEISEIManifest(*static_cast(&sei)); break; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION case SEI::SEI_PREFIX_INDICATION: xWriteSEISEIPrefixIndication(bs, *static_cast(&sei), sps); break; #endif default: assert(!"Trying to write unhandled SEI message"); break; } #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx) { return; } #endif xWriteByteAlign(); } /** * marshal all SEI messages in provided list into one bitstream bs */ Void SEIWriter::writeSEImessages(TComBitIf& bs, const SEIMessages &seiList, const TComSPS *sps, Bool isNested) { #if ENC_DEC_TRACE if (g_HLSTraceEnable) xTraceSEIHeader(); #endif TComBitCounter bs_count; for (SEIMessages::const_iterator sei=seiList.begin(); sei!=seiList.end(); sei++) { xWriteSEImessage(bs, *sei, sps); } if (!isNested) { xWriteRbspTrailingBits(); } } Void SEIWriter::xWriteSEImessage(TComBitIf& bs, const SEI *sei, const TComSPS *sps) { #if ENC_DEC_TRACE if (g_HLSTraceEnable) xTraceSEIHeader(); #endif TComBitCounter bs_count; // calculate how large the payload data is // TODO: this would be far nicer if it used vectored buffers bs_count.resetBits(); setBitstream(&bs_count); #if ENC_DEC_TRACE Bool traceEnable = g_HLSTraceEnable; g_HLSTraceEnable = false; #endif xWriteSEIpayloadData(bs_count, *sei, sps); #if ENC_DEC_TRACE g_HLSTraceEnable = traceEnable; #endif UInt payload_data_num_bits = bs_count.getNumberOfWrittenBits(); assert(0 == payload_data_num_bits % 8); setBitstream(&bs); UInt payloadType = sei->payloadType(); for (; payloadType >= 0xff; payloadType -= 0xff) { WRITE_CODE(0xff, 8, "payload_type"); } WRITE_CODE(payloadType, 8, "payload_type"); UInt payloadSize = payload_data_num_bits/8; for (; payloadSize >= 0xff; payloadSize -= 0xff) { WRITE_CODE(0xff, 8, "payload_size"); } WRITE_CODE(payloadSize, 8, "payload_size"); /* payloadData */ #if ENC_DEC_TRACE if (g_HLSTraceEnable) #if MCTS_EXTRACTION //seems like a leftover copy-paste bug xTraceSEIMessageType(sei->payloadType()); #else //xTraceSEIMessageType((*sei)->payloadType()); #endif #endif xWriteSEIpayloadData(bs, *sei, sps); } Void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei, const TComSPS *sps) { Int i, nalOrVcl; const TComVUI *vui = sps->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); WRITE_UVLC( sei.m_bpSeqParameterSetId, "bp_seq_parameter_set_id" ); if( !hrd->getSubPicCpbParamsPresentFlag() ) { WRITE_FLAG( sei.m_rapCpbParamsPresentFlag, "irap_cpb_params_present_flag" ); } if( sei.m_rapCpbParamsPresentFlag ) { WRITE_CODE( sei.m_cpbDelayOffset, hrd->getCpbRemovalDelayLengthMinus1() + 1, "cpb_delay_offset" ); WRITE_CODE( sei.m_dpbDelayOffset, hrd->getDpbOutputDelayLengthMinus1() + 1, "dpb_delay_offset" ); } WRITE_FLAG( sei.m_concatenationFlag, "concatenation_flag"); WRITE_CODE( sei.m_auCpbRemovalDelayDelta - 1, ( hrd->getCpbRemovalDelayLengthMinus1() + 1 ), "au_cpb_removal_delay_delta_minus1" ); for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) || ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) ) { for( i = 0; i < ( hrd->getCpbCntMinus1( 0 ) + 1 ); i ++ ) { WRITE_CODE( sei.m_initialCpbRemovalDelay[i][nalOrVcl],( hrd->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , "initial_cpb_removal_delay" ); WRITE_CODE( sei.m_initialCpbRemovalDelayOffset[i][nalOrVcl],( hrd->getInitialCpbRemovalDelayLengthMinus1() + 1 ), "initial_cpb_removal_delay_offset" ); if( hrd->getSubPicCpbParamsPresentFlag() || sei.m_rapCpbParamsPresentFlag ) { WRITE_CODE( sei.m_initialAltCpbRemovalDelay[i][nalOrVcl], ( hrd->getInitialCpbRemovalDelayLengthMinus1() + 1 ) , "initial_alt_cpb_removal_delay" ); WRITE_CODE( sei.m_initialAltCpbRemovalDelayOffset[i][nalOrVcl], ( hrd->getInitialCpbRemovalDelayLengthMinus1() + 1 ),"initial_alt_cpb_removal_delay_offset" ); } } } } } Void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const TComSPS *sps) { Int i; const TComVUI *vui = sps->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); if( vui->getFrameFieldInfoPresentFlag() ) { WRITE_CODE( sei.m_picStruct, 4, "pic_struct" ); WRITE_CODE( sei.m_sourceScanType, 2, "source_scan_type" ); WRITE_FLAG( sei.m_duplicateFlag ? 1 : 0, "duplicate_flag" ); } if( hrd->getCpbDpbDelaysPresentFlag() ) { WRITE_CODE( sei.m_auCpbRemovalDelay - 1, ( hrd->getCpbRemovalDelayLengthMinus1() + 1 ), "au_cpb_removal_delay_minus1" ); WRITE_CODE( sei.m_picDpbOutputDelay, ( hrd->getDpbOutputDelayLengthMinus1() + 1 ), "pic_dpb_output_delay" ); if(hrd->getSubPicCpbParamsPresentFlag()) { WRITE_CODE(sei.m_picDpbOutputDuDelay, hrd->getDpbOutputDelayDuLengthMinus1()+1, "pic_dpb_output_du_delay" ); } if( hrd->getSubPicCpbParamsPresentFlag() && hrd->getSubPicCpbParamsInPicTimingSEIFlag() ) { WRITE_UVLC( sei.m_numDecodingUnitsMinus1, "num_decoding_units_minus1" ); WRITE_FLAG( sei.m_duCommonCpbRemovalDelayFlag, "du_common_cpb_removal_delay_flag" ); if( sei.m_duCommonCpbRemovalDelayFlag ) { WRITE_CODE( sei.m_duCommonCpbRemovalDelayMinus1, ( hrd->getDuCpbRemovalDelayLengthMinus1() + 1 ), "du_common_cpb_removal_delay_minus1" ); } for( i = 0; i <= sei.m_numDecodingUnitsMinus1; i ++ ) { WRITE_UVLC( sei.m_numNalusInDuMinus1[ i ], "num_nalus_in_du_minus1"); if( ( !sei.m_duCommonCpbRemovalDelayFlag ) && ( i < sei.m_numDecodingUnitsMinus1 ) ) { WRITE_CODE( sei.m_duCpbRemovalDelayMinus1[ i ], ( hrd->getDuCpbRemovalDelayLengthMinus1() + 1 ), "du_cpb_removal_delay_minus1" ); } } } } } Void SEIWriter::xWriteSEIPanScanRect(const SEIPanScanRect &sei) { WRITE_UVLC( sei.m_panScanRectId, "pan_scan_rect_id" ); const UInt numRegions = (UInt) sei.m_panScanRectRegions.size(); if ( !sei.m_panScanRectCancelFlag && numRegions>0 ) { WRITE_FLAG( sei.m_panScanRectCancelFlag, "pan_scan_rect_cancel_flag" ); WRITE_UVLC( numRegions - 1, "pan_scan_cnt_minus1" ); for(UInt region=0; region255) ? 0xff : sei.m_ituCountryCode, 8, "itu_t_t35_country_code" ); if (sei.m_ituCountryCode>=255) { assert(sei.m_ituCountryCode < 255+256); WRITE_CODE( sei.m_ituCountryCode-255, 8, "itu_t_t35_country_code_extension_byte" ); } for(UInt i=0; i 3) { WRITE_UVLC( sei.m_secondSceneId, "second_scene_id" ); } } } Void SEIWriter::xWriteSEIPictureSnapshot(const SEIPictureSnapshot &sei) { WRITE_UVLC( sei.m_snapshotId, "snapshot_id" ); } Void SEIWriter::xWriteSEIProgressiveRefinementSegmentStart(const SEIProgressiveRefinementSegmentStart &sei) { WRITE_UVLC( sei.m_progressiveRefinementId, "progressive_refinement_id" ); WRITE_UVLC( sei.m_picOrderCntDelta, "pic_order_cnt_delta" ); } Void SEIWriter::xWriteSEIProgressiveRefinementSegmentEnd(const SEIProgressiveRefinementSegmentEnd &sei) { WRITE_UVLC( sei.m_progressiveRefinementId, "progressive_refinement_id" ); } Void SEIWriter::xWriteSEIFilmGrainCharacteristics(const SEIFilmGrainCharacteristics &sei) { WRITE_FLAG( sei.m_filmGrainCharacteristicsCancelFlag, "film_grain_characteristics_cancel_flag" ); if (!sei.m_filmGrainCharacteristicsCancelFlag) { WRITE_CODE( sei.m_filmGrainModelId, 2, "film_grain_model_id" ); WRITE_FLAG( sei.m_separateColourDescriptionPresentFlag, "separate_colour_description_present_flag" ); if (sei.m_separateColourDescriptionPresentFlag) { WRITE_CODE( sei.m_filmGrainBitDepthLumaMinus8, 3, "film_grain_bit_depth_luma_minus8" ); WRITE_CODE( sei.m_filmGrainBitDepthChromaMinus8, 3, "film_grain_bit_depth_chroma_minus8" ); WRITE_FLAG( sei.m_filmGrainFullRangeFlag, "film_grain_full_range_flag" ); WRITE_CODE( sei.m_filmGrainColourPrimaries, 8, "film_grain_colour_primaries" ); WRITE_CODE( sei.m_filmGrainTransferCharacteristics, 8, "film_grain_transfer_characteristics" ); WRITE_CODE( sei.m_filmGrainMatrixCoeffs, 8, "film_grain_matrix_coeffs" ); } WRITE_CODE( sei.m_blendingModeId, 2, "blending_mode_id" ); WRITE_CODE( sei.m_log2ScaleFactor, 4, "log2_scale_factor" ); for(Int c=0; c<3; c++) { const SEIFilmGrainCharacteristics::CompModel &cm=sei.m_compModel[c]; #if JVET_X0048_X0103_FILM_GRAIN const UInt numIntensityIntervals = (UInt) cm.numIntensityIntervals; #else const UInt numIntensityIntervals = (UInt) cm.intensityValues.size(); #endif const UInt numModelValues = cm.numModelValues; WRITE_FLAG( sei.m_compModel[c].bPresentFlag && numIntensityIntervals>0 && numModelValues>0, "comp_model_present_flag[c]" ); } for(Int c=0; c<3; c++) { const SEIFilmGrainCharacteristics::CompModel &cm=sei.m_compModel[c]; #if JVET_X0048_X0103_FILM_GRAIN const UInt numIntensityIntervals = (UInt) cm.numIntensityIntervals; #else const UInt numIntensityIntervals = (UInt) cm.intensityValues.size(); #endif const UInt numModelValues = cm.numModelValues; if (cm.bPresentFlag && numIntensityIntervals>0 && numModelValues>0) { assert(numIntensityIntervals<=256); assert(numModelValues<=8); WRITE_CODE( numIntensityIntervals-1, 8, "num_intensity_intervals_minus1[c]"); WRITE_CODE( numModelValues-1, 3, "num_model_values_minus1[c]"); for(UInt interval=0; intervalgetChromaFormatIdc() == CHROMA_400) == sei.m_bIsMonochrome ); const UInt numChromaChannels = sei.m_bIsMonochrome ? 1:3; assert( sei.m_filterHintValues.size() == numChromaChannels*sei.m_filterHintSizeX*sei.m_filterHintSizeY ); for(std::size_t i=0; i> 3 ) << 3, "start_of_coded_interval" ); } break; } case 3: { WRITE_CODE( sei.m_numPivots, 16, "num_pivots" ); for(i = 0; i < sei.m_numPivots; i++ ) { WRITE_CODE( sei.m_codedPivotValue[i], (( sei.m_codedDataBitDepth + 7 ) >> 3 ) << 3, "coded_pivot_value" ); WRITE_CODE( sei.m_targetPivotValue[i], (( sei.m_targetBitDepth + 7 ) >> 3 ) << 3, "target_pivot_value"); } break; } case 4: { WRITE_CODE( sei.m_cameraIsoSpeedIdc, 8, "camera_iso_speed_idc" ); if( sei.m_cameraIsoSpeedIdc == 255) //Extended_ISO { WRITE_CODE( sei.m_cameraIsoSpeedValue, 32, "camera_iso_speed_value" ); } WRITE_CODE( sei.m_exposureIndexIdc, 8, "exposure_index_idc" ); if( sei.m_exposureIndexIdc == 255) //Extended_ISO { WRITE_CODE( sei.m_exposureIndexValue, 32, "exposure_index_value" ); } WRITE_FLAG( sei.m_exposureCompensationValueSignFlag, "exposure_compensation_value_sign_flag" ); WRITE_CODE( sei.m_exposureCompensationValueNumerator, 16, "exposure_compensation_value_numerator" ); WRITE_CODE( sei.m_exposureCompensationValueDenomIdc, 16, "exposure_compensation_value_denom_idc" ); WRITE_CODE( sei.m_refScreenLuminanceWhite, 32, "ref_screen_luminance_white" ); WRITE_CODE( sei.m_extendedRangeWhiteLevel, 32, "extended_range_white_level" ); WRITE_CODE( sei.m_nominalBlackLevelLumaCodeValue, 16, "nominal_black_level_luma_code_value" ); WRITE_CODE( sei.m_nominalWhiteLevelLumaCodeValue, 16, "nominal_white_level_luma_code_value" ); WRITE_CODE( sei.m_extendedWhiteLevelLumaCodeValue, 16, "extended_white_level_luma_code_value" ); break; } default: { assert(!"Undefined SEIToneMapModelId"); break; } }//switch m_modelId }//if(!sei.m_toneMapCancelFlag) } Void SEIWriter::xWriteSEIFramePacking(const SEIFramePacking& sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx #endif ) { #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx) { int numBits = 0; numBits += getBitsUe(sei.m_arrangementId); if (!sei.m_arrangementCancelFlag) { numBits += 9; } else { numBits += 2; } WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); } #endif WRITE_UVLC( sei.m_arrangementId, "frame_packing_arrangement_id" ); WRITE_FLAG( sei.m_arrangementCancelFlag, "frame_packing_arrangement_cancel_flag" ); if( sei.m_arrangementCancelFlag == 0 ) { WRITE_CODE( sei.m_arrangementType, 7, "frame_packing_arrangement_type" ); #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx) { return; } #endif WRITE_FLAG( sei.m_quincunxSamplingFlag, "quincunx_sampling_flag" ); WRITE_CODE( sei.m_contentInterpretationType, 6, "content_interpretation_type" ); WRITE_FLAG( sei.m_spatialFlippingFlag, "spatial_flipping_flag" ); WRITE_FLAG( sei.m_frame0FlippedFlag, "frame0_flipped_flag" ); WRITE_FLAG( sei.m_fieldViewsFlag, "field_views_flag" ); WRITE_FLAG( sei.m_currentFrameIsFrame0Flag, "current_frame_is_frame0_flag" ); WRITE_FLAG( sei.m_frame0SelfContainedFlag, "frame0_self_contained_flag" ); WRITE_FLAG( sei.m_frame1SelfContainedFlag, "frame1_self_contained_flag" ); if(sei.m_quincunxSamplingFlag == 0 && sei.m_arrangementType != 5) { WRITE_CODE( sei.m_frame0GridPositionX, 4, "frame0_grid_position_x" ); WRITE_CODE( sei.m_frame0GridPositionY, 4, "frame0_grid_position_y" ); WRITE_CODE( sei.m_frame1GridPositionX, 4, "frame1_grid_position_x" ); WRITE_CODE( sei.m_frame1GridPositionY, 4, "frame1_grid_position_y" ); } WRITE_CODE( sei.m_arrangementReservedByte, 8, "frame_packing_arrangement_reserved_byte" ); WRITE_FLAG( sei.m_arrangementPersistenceFlag, "frame_packing_arrangement_persistence_flag" ); } WRITE_FLAG( sei.m_upsampledAspectRatio, "upsampled_aspect_ratio" ); } Void SEIWriter::xWriteSEIDisplayOrientation(const SEIDisplayOrientation &sei) { WRITE_FLAG( sei.cancelFlag, "display_orientation_cancel_flag" ); if( !sei.cancelFlag ) { WRITE_FLAG( sei.horFlip, "hor_flip" ); WRITE_FLAG( sei.verFlip, "ver_flip" ); WRITE_CODE( sei.anticlockwiseRotation, 16, "anticlockwise_rotation" ); WRITE_FLAG( sei.persistenceFlag, "display_orientation_persistence_flag" ); } } Void SEIWriter::xWriteSEIGreenMetadataInfo(const SEIGreenMetadataInfo& sei) { WRITE_CODE(sei.m_greenMetadataType, 8, "green_metadata_type"); WRITE_CODE(sei.m_xsdMetricType, 8, "xsd_metric_type"); WRITE_CODE(sei.m_xsdMetricValue, 16, "xsd_metric_value"); } Void SEIWriter::xWriteSEISOPDescription(const SEISOPDescription& sei) { WRITE_UVLC( sei.m_sopSeqParameterSetId, "sop_seq_parameter_set_id" ); WRITE_UVLC( sei.m_numPicsInSopMinus1, "num_pics_in_sop_minus1" ); for (UInt i = 0; i <= sei.m_numPicsInSopMinus1; i++) { WRITE_CODE( sei.m_sopDescVclNaluType[i], 6, "sop_desc_vcl_nalu_type" ); WRITE_CODE( sei.m_sopDescTemporalId[i], 3, "sop_desc_temporal_id" ); if (sei.m_sopDescVclNaluType[i] != NAL_UNIT_CODED_SLICE_IDR_W_RADL && sei.m_sopDescVclNaluType[i] != NAL_UNIT_CODED_SLICE_IDR_N_LP) { WRITE_UVLC( sei.m_sopDescStRpsIdx[i], "sop_desc_st_rps_idx" ); } if (i > 0) { WRITE_SVLC( sei.m_sopDescPocDelta[i], "sop_desc_poc_delta" ); } } } Void SEIWriter::xWriteSEIActiveParameterSets(const SEIActiveParameterSets& sei) { WRITE_CODE(sei.activeVPSId, 4, "active_video_parameter_set_id"); WRITE_FLAG(sei.m_selfContainedCvsFlag, "self_contained_cvs_flag"); WRITE_FLAG(sei.m_noParameterSetUpdateFlag, "no_parameter_set_update_flag"); WRITE_UVLC(sei.numSpsIdsMinus1, "num_sps_ids_minus1"); assert (sei.activeSeqParameterSetId.size() == (sei.numSpsIdsMinus1 + 1)); for (Int i = 0; i < sei.activeSeqParameterSetId.size(); i++) { WRITE_UVLC(sei.activeSeqParameterSetId[i], "active_seq_parameter_set_id"); } } Void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const TComSPS *sps) { const TComVUI *vui = sps->getVuiParameters(); WRITE_UVLC(sei.m_decodingUnitIdx, "decoding_unit_idx"); if(vui->getHrdParameters()->getSubPicCpbParamsInPicTimingSEIFlag()) { WRITE_CODE( sei.m_duSptCpbRemovalDelay, (vui->getHrdParameters()->getDuCpbRemovalDelayLengthMinus1() + 1), "du_spt_cpb_removal_delay_increment"); } WRITE_FLAG( sei.m_dpbOutputDuDelayPresentFlag, "dpb_output_du_delay_present_flag"); if(sei.m_dpbOutputDuDelayPresentFlag) { WRITE_CODE(sei.m_picSptDpbOutputDuDelay, vui->getHrdParameters()->getDpbOutputDelayDuLengthMinus1() + 1, "pic_spt_dpb_output_du_delay"); } } Void SEIWriter::xWriteSEITemporalLevel0Index(const SEITemporalLevel0Index &sei) { WRITE_CODE( sei.tl0Idx, 8 , "tl0_idx" ); WRITE_CODE( sei.rapIdx, 8 , "rap_idx" ); } Void SEIWriter::xWriteSEIDecodedPictureHash(const SEIDecodedPictureHash& sei) { const TChar *traceString="\0"; switch (sei.method) { case HASHTYPE_MD5: traceString="picture_md5"; break; case HASHTYPE_CRC: traceString="picture_crc"; break; case HASHTYPE_CHECKSUM: traceString="picture_checksum"; break; default: assert(false); break; } if (traceString != 0) //use of this variable is needed to avoid a compiler error with G++ 4.6.1 { WRITE_CODE(sei.method, 8, "hash_type"); for(UInt i=0; igetNumberOfWrittenBits() % 8 != 0 ) { WRITE_FLAG( 0, "nesting_zero_bit" ); } // write nested SEI messages writeSEImessages(bs, sei.m_nestedSEIs, sps, true); } Void SEIWriter::xWriteSEIRegionRefreshInfo(const SEIRegionRefreshInfo &sei) { WRITE_FLAG( sei.m_gdrForegroundFlag, "gdr_foreground_flag"); } Void SEIWriter::xWriteSEINoDisplay(const SEINoDisplay& /*sei*/) { // intentionally empty } Void SEIWriter::xWriteSEITimeCode(const SEITimeCode& sei) { WRITE_CODE(sei.numClockTs, 2, "num_clock_ts"); for(Int i = 0; i < sei.numClockTs; i++) { const TComSEITimeSet ¤tTimeSet = sei.timeSetArray[i]; WRITE_FLAG(currentTimeSet.clockTimeStampFlag, "clock_time_stamp_flag"); if(currentTimeSet.clockTimeStampFlag) { WRITE_FLAG(currentTimeSet.numUnitFieldBasedFlag, "units_field_based_flag"); WRITE_CODE(currentTimeSet.countingType, 5, "counting_type"); WRITE_FLAG(currentTimeSet.fullTimeStampFlag, "full_timestamp_flag"); WRITE_FLAG(currentTimeSet.discontinuityFlag, "discontinuity_flag"); WRITE_FLAG(currentTimeSet.cntDroppedFlag, "cnt_dropped_flag"); WRITE_CODE(currentTimeSet.numberOfFrames, 9, "n_frames"); if(currentTimeSet.fullTimeStampFlag) { WRITE_CODE(currentTimeSet.secondsValue, 6, "seconds_value"); WRITE_CODE(currentTimeSet.minutesValue, 6, "minutes_value"); WRITE_CODE(currentTimeSet.hoursValue, 5, "hours_value"); } else { WRITE_FLAG(currentTimeSet.secondsFlag, "seconds_flag"); if(currentTimeSet.secondsFlag) { WRITE_CODE(currentTimeSet.secondsValue, 6, "seconds_value"); WRITE_FLAG(currentTimeSet.minutesFlag, "minutes_flag"); if(currentTimeSet.minutesFlag) { WRITE_CODE(currentTimeSet.minutesValue, 6, "minutes_value"); WRITE_FLAG(currentTimeSet.hoursFlag, "hours_flag"); if(currentTimeSet.hoursFlag) { WRITE_CODE(currentTimeSet.hoursValue, 5, "hours_value"); } } } } WRITE_CODE(currentTimeSet.timeOffsetLength, 5, "time_offset_length"); if(currentTimeSet.timeOffsetLength > 0) { if(currentTimeSet.timeOffsetValue >= 0) { WRITE_CODE((UInt)currentTimeSet.timeOffsetValue, currentTimeSet.timeOffsetLength, "time_offset_value"); } else { // Two's complement conversion UInt offsetValue = ~(currentTimeSet.timeOffsetValue) + 1; offsetValue |= (1 << (currentTimeSet.timeOffsetLength-1)); WRITE_CODE(offsetValue, currentTimeSet.timeOffsetLength, "time_offset_value"); } } } } } Void SEIWriter::xWriteSEIMasteringDisplayColourVolume(const SEIMasteringDisplayColourVolume& sei) { WRITE_CODE( sei.values.primaries[0][0], 16, "display_primaries_x[0]" ); WRITE_CODE( sei.values.primaries[0][1], 16, "display_primaries_y[0]" ); WRITE_CODE( sei.values.primaries[1][0], 16, "display_primaries_x[1]" ); WRITE_CODE( sei.values.primaries[1][1], 16, "display_primaries_y[1]" ); WRITE_CODE( sei.values.primaries[2][0], 16, "display_primaries_x[2]" ); WRITE_CODE( sei.values.primaries[2][1], 16, "display_primaries_y[2]" ); WRITE_CODE( sei.values.whitePoint[0], 16, "white_point_x" ); WRITE_CODE( sei.values.whitePoint[1], 16, "white_point_y" ); WRITE_CODE( sei.values.maxLuminance, 32, "max_display_mastering_luminance" ); WRITE_CODE( sei.values.minLuminance, 32, "min_display_mastering_luminance" ); } Void SEIWriter::xWriteSEISegmentedRectFramePacking(const SEISegmentedRectFramePacking& sei) { WRITE_FLAG( sei.m_arrangementCancelFlag, "segmented_rect_frame_packing_arrangement_cancel_flag" ); if( sei.m_arrangementCancelFlag == 0 ) { WRITE_CODE( sei.m_contentInterpretationType, 2, "segmented_rect_content_interpretation_type" ); WRITE_FLAG( sei.m_arrangementPersistenceFlag, "segmented_rect_frame_packing_arrangement_persistence" ); } } Void SEIWriter::xWriteSEITempMotionConstrainedTileSets(const SEITempMotionConstrainedTileSets& sei) { //UInt code; WRITE_FLAG((sei.m_mc_all_tiles_exact_sample_value_match_flag ? 1 : 0), "mc_all_tiles_exact_sample_value_match_flag"); WRITE_FLAG((sei.m_each_tile_one_tile_set_flag ? 1 : 0), "each_tile_one_tile_set_flag" ); if(!sei.m_each_tile_one_tile_set_flag) { WRITE_FLAG((sei.m_limited_tile_set_display_flag ? 1 : 0), "limited_tile_set_display_flag"); WRITE_UVLC((sei.getNumberOfTileSets() - 1), "num_sets_in_message_minus1" ); if(sei.getNumberOfTileSets() > 0) { for(Int i = 0; i < sei.getNumberOfTileSets(); i++) { WRITE_UVLC(sei.tileSetData(i).m_mcts_id, "mcts_id"); if(sei.m_limited_tile_set_display_flag) { WRITE_FLAG((sei.tileSetData(i).m_display_tile_set_flag ? 1 : 0), "display_tile_set_flag"); } WRITE_UVLC((sei.tileSetData(i).getNumberOfTileRects() - 1), "num_tile_rects_in_set_minus1"); for(Int j = 0; j < sei.tileSetData(i).getNumberOfTileRects(); j++) { WRITE_UVLC(sei.tileSetData(i).topLeftTileIndex (j), "top_left_tile_index"); WRITE_UVLC(sei.tileSetData(i).bottomRightTileIndex(j), "bottom_right_tile_index"); } if(!sei.m_mc_all_tiles_exact_sample_value_match_flag) { WRITE_FLAG((sei.tileSetData(i).m_exact_sample_value_match_flag ? 1 : 0), "exact_sample_value_match_flag"); } WRITE_FLAG((sei.tileSetData(i).m_mcts_tier_level_idc_present_flag ? 1 : 0), "mcts_tier_level_idc_present_flag"); if(sei.tileSetData(i).m_mcts_tier_level_idc_present_flag) { WRITE_FLAG((sei.tileSetData(i).m_mcts_tier_flag ? 1 : 0), "mcts_tier_flag"); WRITE_CODE( sei.tileSetData(i).m_mcts_level_idc, 8, "mcts_level_idc"); } } } } else { WRITE_FLAG((sei.m_max_mcs_tier_level_idc_present_flag ? 1 : 0), "max_mcs_tier_level_idc_present_flag"); if(sei.m_max_mcs_tier_level_idc_present_flag) { WRITE_FLAG((sei.m_max_mcts_tier_flag ? 1 : 0), "max_mcts_tier_flag"); WRITE_CODE( sei.m_max_mcts_level_idc, 8, "max_mcts_level_idc"); } } } #if MCTS_EXTRACTION Void SEIWriter::xWriteSEIMCTSExtractionInfoSet(const SEIMCTSExtractionInfoSet& sei) { assert(!sei.m_MCTSExtractionInfoSets.empty()); WRITE_UVLC(((UInt)sei.m_MCTSExtractionInfoSets.size() - 1), "num_sets_in_message_minus1"); for (std::vector::const_iterator MCTSEISiter = sei.m_MCTSExtractionInfoSets.begin(); MCTSEISiter != sei.m_MCTSExtractionInfoSets.end(); MCTSEISiter++) { WRITE_UVLC(((UInt)MCTSEISiter->m_idxOfMctsInSet.size() - 1), "num_mcts_sets_minus1[ i ]"); for ( Int j = 0; j < MCTSEISiter->m_idxOfMctsInSet.size(); j++) { WRITE_UVLC(((UInt)MCTSEISiter->m_idxOfMctsInSet[j].size() - 1), "num_mcts_in_set_minus1[ i ][ j ]"); for (Int k = 0; k < MCTSEISiter->m_idxOfMctsInSet[j].size(); k++) { WRITE_UVLC((MCTSEISiter->m_idxOfMctsInSet[j][k]), "idx_of_mcts_in_set[ i ][ j ][ k ]"); } } WRITE_FLAG((MCTSEISiter->m_sliceReorderingEnabledFlag? 1 : 0 ), "slice_reordering_enabled_flag[ i ]"); if ( MCTSEISiter->m_sliceReorderingEnabledFlag ) { WRITE_UVLC(((UInt)MCTSEISiter->m_outputSliceSegmentAddress.size() - 1), "num_slice_segments_minus1[ i ]"); for (Int j = 0; j < MCTSEISiter->m_outputSliceSegmentAddress.size(); j++) { WRITE_UVLC((MCTSEISiter->m_outputSliceSegmentAddress[j]), "output_slice_segment_address[ i ][ j ]"); } } WRITE_UVLC(((UInt)MCTSEISiter->m_vpsRbspDataLength.size() - 1), "num_vps_in_info_set_minus1[i]"); for (Int j = 0; j < MCTSEISiter->m_vpsRbspDataLength.size(); j++) { WRITE_UVLC((MCTSEISiter->m_vpsRbspDataLength[j]), "vps_rbsp_data_length[i][j]"); } WRITE_UVLC(((UInt)MCTSEISiter->m_spsRbspDataLength.size() - 1), "num_sps_in_info_set_minus1[i]"); for (Int j = 0; j < MCTSEISiter->m_spsRbspDataLength.size(); j++) { WRITE_UVLC((MCTSEISiter->m_spsRbspDataLength[j]), "sps_rbsp_data_length[i][j]"); } WRITE_UVLC(((UInt)MCTSEISiter->m_ppsRbspDataLength.size() - 1), "num_sps_in_info_set_minus1[i]"); for (Int j = 0; j < MCTSEISiter->m_ppsRbspDataLength.size(); j++) { WRITE_UVLC((MCTSEISiter->m_ppsNuhTemporalIdPlus1[j]), "pps_nuh_temporal_id_plus1[i][j]"); WRITE_UVLC((MCTSEISiter->m_ppsRbspDataLength[j]), "pps_rbsp_data_length[i][j]"); } // byte alignment while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) { WRITE_FLAG(0, "mcts_alignment_bit_equal_to_zero"); } for (Int j = 0; j < MCTSEISiter->m_vpsRbspData.size(); j++) { for (Int k = 0; k < MCTSEISiter->m_vpsRbspDataLength[j]; k++) { WRITE_CODE((MCTSEISiter->m_vpsRbspData[j][k]), 8, "vps_rbsp_data_byte[ i ][ j ][ k ]"); } } for (Int j = 0; j < MCTSEISiter->m_spsRbspData.size(); j++) { for (Int k = 0; k < MCTSEISiter->m_spsRbspDataLength[j]; k++) { WRITE_CODE((MCTSEISiter->m_spsRbspData[j][k]), 8, "sps_rbsp_data_byte[ i ][ j ][ k ]"); } } for (Int j = 0; j < MCTSEISiter->m_ppsRbspData.size(); j++) { for (Int k = 0; k < MCTSEISiter->m_ppsRbspDataLength[j]; k++) { WRITE_CODE((MCTSEISiter->m_ppsRbspData[j][k]), 8, "pps_rbsp_data_byte[ i ][ j ][ k ]"); } } } } #endif Void SEIWriter::xWriteSEIChromaResamplingFilterHint(const SEIChromaResamplingFilterHint &sei) { WRITE_CODE(sei.m_verChromaFilterIdc, 8, "ver_chroma_filter_idc"); WRITE_CODE(sei.m_horChromaFilterIdc, 8, "hor_chroma_filter_idc"); WRITE_FLAG(sei.m_verFilteringFieldProcessingFlag, "ver_filtering_field_processing_flag"); if(sei.m_verChromaFilterIdc == 1 || sei.m_horChromaFilterIdc == 1) { WRITE_UVLC(sei.m_targetFormatIdc, "target_format_idc"); if(sei.m_verChromaFilterIdc == 1) { const Int numVerticalFilter = (Int)sei.m_verFilterCoeff.size(); WRITE_UVLC(numVerticalFilter, "num_vertical_filters"); if(numVerticalFilter > 0) { for(Int i = 0; i < numVerticalFilter; i ++) { const Int verTapLengthMinus1 = (Int) sei.m_verFilterCoeff[i].size() - 1; WRITE_UVLC(verTapLengthMinus1, "ver_tap_length_minus_1"); for(Int j = 0; j < (verTapLengthMinus1 + 1); j ++) { WRITE_SVLC(sei.m_verFilterCoeff[i][j], "ver_filter_coeff"); } } } } if(sei.m_horChromaFilterIdc == 1) { const Int numHorizontalFilter = (Int) sei.m_horFilterCoeff.size(); WRITE_UVLC(numHorizontalFilter, "num_horizontal_filters"); if(numHorizontalFilter > 0) { for(Int i = 0; i < numHorizontalFilter; i ++) { const Int horTapLengthMinus1 = (Int) sei.m_horFilterCoeff[i].size() - 1; WRITE_UVLC(horTapLengthMinus1, "hor_tap_length_minus_1"); for(Int j = 0; j < (horTapLengthMinus1 + 1); j ++) { WRITE_SVLC(sei.m_horFilterCoeff[i][j], "hor_filter_coeff"); } } } } } } Void SEIWriter::xWriteSEIKneeFunctionInfo(const SEIKneeFunctionInfo &sei) { WRITE_UVLC( sei.m_kneeId, "knee_function_id" ); WRITE_FLAG( sei.m_kneeCancelFlag, "knee_function_cancel_flag" ); if ( !sei.m_kneeCancelFlag ) { WRITE_FLAG( sei.m_kneePersistenceFlag, "knee_function_persistence_flag" ); WRITE_CODE( (UInt)sei.m_kneeInputDrange , 32, "input_d_range" ); WRITE_CODE( (UInt)sei.m_kneeInputDispLuminance, 32, "input_disp_luminance" ); WRITE_CODE( (UInt)sei.m_kneeOutputDrange, 32, "output_d_range" ); WRITE_CODE( (UInt)sei.m_kneeOutputDispLuminance, 32, "output_disp_luminance" ); WRITE_UVLC( sei.m_kneeNumKneePointsMinus1, "num_knee_points_minus1" ); for(Int i = 0; i <= sei.m_kneeNumKneePointsMinus1; i++ ) { WRITE_CODE( (UInt)sei.m_kneeInputKneePoint[i], 10,"input_knee_point" ); WRITE_CODE( (UInt)sei.m_kneeOutputKneePoint[i], 10, "output_knee_point" ); } } } Void SEIWriter::xWriteSEIContentColourVolume(const SEIContentColourVolume &sei) { WRITE_FLAG(sei.m_ccvCancelFlag, "ccv_cancel_flag"); if (!sei.m_ccvCancelFlag) { WRITE_FLAG(sei.m_ccvPersistenceFlag, "ccv_persistence_flag"); WRITE_FLAG(sei.m_ccvPrimariesPresentFlag, "ccv_primaries_present_flag"); WRITE_FLAG(sei.m_ccvMinLuminanceValuePresentFlag, "ccv_min_luminance_value_present_flag"); WRITE_FLAG(sei.m_ccvMaxLuminanceValuePresentFlag, "ccv_max_luminance_value_present_flag"); WRITE_FLAG(sei.m_ccvAvgLuminanceValuePresentFlag, "ccv_avg_luminance_value_present_flag"); if (sei.m_ccvPrimariesPresentFlag == true) { for (Int i = 0; i < MAX_NUM_COMPONENT; i++) { WRITE_SCODE((Int) sei.m_ccvPrimariesX[i], 32, "ccv_primaries_x[i]"); WRITE_SCODE((Int) sei.m_ccvPrimariesY[i], 32, "ccv_primaries_y[i]"); } } if (sei.m_ccvMinLuminanceValuePresentFlag == true) { WRITE_CODE( (UInt)sei.m_ccvMinLuminanceValue, 32, "ccv_min_luminance_value" ); } if (sei.m_ccvMaxLuminanceValuePresentFlag == true) { WRITE_CODE( (UInt)sei.m_ccvMaxLuminanceValue, 32, "ccv_max_luminance_value" ); } if (sei.m_ccvAvgLuminanceValuePresentFlag == true) { WRITE_CODE( (UInt)sei.m_ccvAvgLuminanceValue, 32, "ccv_avg_luminance_value" ); } } } #if SHUTTER_INTERVAL_SEI_MESSAGE Void SEIWriter::xWriteSEIShutterInterval(const SEIShutterIntervalInfo &sei) { WRITE_CODE(sei.m_siiTimeScale, 32, "sii_time_scale"); WRITE_FLAG(sei.m_siiFixedSIwithinCLVS, "fixed_shutter_interval_within_clvs_flag"); if (sei.m_siiFixedSIwithinCLVS) { WRITE_CODE(sei.m_siiNumUnitsInShutterInterval, 32, "sii_num_units_in_shutter_interval"); } else { WRITE_CODE(sei.m_siiMaxSubLayersMinus1, 3, "sii_max_sub_layers_minus1"); for (UInt i = 0; i <= sei.m_siiMaxSubLayersMinus1; i++) { WRITE_CODE(sei.m_siiSubLayerNumUnitsInSI[i], 32, "sub_layer_num_units_in_shutter_interval[ i ]"); } } } #endif Void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProjection &sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx #endif ) { #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx) { int numBits = 5; if (sei.m_erpGuardBandFlag) { numBits += 19; } WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); } #endif WRITE_FLAG( sei.m_erpCancelFlag, "erp_cancel_flag" ); if( !sei.m_erpCancelFlag ) { WRITE_FLAG( sei.m_erpPersistenceFlag, "erp_persistence_flag" ); WRITE_FLAG( sei.m_erpGuardBandFlag, "erp_guard_band_flag" ); WRITE_CODE( 0, 2, "erp_reserved_zero_2bits" ); if ( sei.m_erpGuardBandFlag == 1) { WRITE_CODE( sei.m_erpGuardBandType, 3, "erp_guard_band_type" ); WRITE_CODE( sei.m_erpLeftGuardBandWidth, 8, "erp_left_guard_band_width" ); WRITE_CODE( sei.m_erpRightGuardBandWidth, 8, "erp_right_guard_band_width" ); } } } Void SEIWriter::xWriteSEISphereRotation(const SEISphereRotation &sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx #endif ) { #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx) { if (sei.m_sphereRotationCancelFlag) { WRITE_CODE(0, 8, "num_sei_prefix_indications_minus1"); } else { WRITE_CODE(1, 8, "num_sei_prefix_indications_minus1"); } int numBits = 8; WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); } #endif WRITE_FLAG( sei.m_sphereRotationCancelFlag, "sphere_rotation_cancel_flag" ); if( !sei.m_sphereRotationCancelFlag ) { WRITE_FLAG( sei.m_sphereRotationPersistenceFlag, "sphere_rotation_persistence_flag" ); WRITE_CODE( 0, 6, "sphere_rotation_reserved_zero_6bits" ); #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (SEIPrefixIndicationIdx >= 2) { xWriteSEIPrefixIndicationByteAlign(); int numBits2 = 32 + 32 + 32 + 8; WRITE_CODE(numBits2 - 1, 16, "num_bits_in_prefix_indication_minus1"); WRITE_FLAG(sei.m_sphereRotationCancelFlag, "sphere_rotation_cancel_flag"); WRITE_FLAG(sei.m_sphereRotationPersistenceFlag, "sphere_rotation_persistence_flag"); WRITE_CODE(0, 6, "sphere_rotation_reserved_zero_6bits"); } #endif WRITE_SCODE(sei.m_sphereRotationYaw, 32, "sphere_rotation_yaw" ); WRITE_SCODE(sei.m_sphereRotationPitch, 32, "sphere_rotation_pitch" ); WRITE_SCODE(sei.m_sphereRotationRoll, 32, "sphere_rotation_roll" ); } } Void SEIWriter::xWriteSEIOmniViewport(const SEIOmniViewport &sei) { WRITE_CODE( sei.m_omniViewportId, 10, "omni_viewport_id" ); WRITE_FLAG( sei.m_omniViewportCancelFlag, "omni_viewport_cancel_flag" ); if ( !sei.m_omniViewportCancelFlag ) { WRITE_FLAG( sei.m_omniViewportPersistenceFlag, "omni_viewport_persistence_flag" ); const UInt numRegions = (UInt) sei.m_omniViewportRegions.size(); WRITE_CODE( numRegions - 1, 4, "omni_viewport_cnt_minus1" ); for(UInt region=0; region0 ) { for( Int i=0 ; i<=sei.m_preLutNumValMinus1[c] ; i++ ) { WRITE_CODE( sei.m_preLut[c][i].codedValue, (( sei.m_colourRemapInputBitDepth + 7 ) >> 3 ) << 3, "pre_lut_coded_value[c][i]" ); WRITE_CODE( sei.m_preLut[c][i].targetValue, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, "pre_lut_target_value[c][i]" ); } } } WRITE_FLAG( sei.m_colourRemapMatrixPresentFlag, "colour_remap_matrix_present_flag" ); if( sei.m_colourRemapMatrixPresentFlag ) { WRITE_CODE( sei.m_log2MatrixDenom, 4, "log2_matrix_denom" ); for( Int c=0 ; c<3 ; c++ ) { for( Int i=0 ; i<3 ; i++ ) { WRITE_SVLC( sei.m_colourRemapCoeffs[c][i], "colour_remap_coeffs[c][i]" ); } } } for( Int c=0 ; c<3 ; c++ ) { WRITE_CODE( sei.m_postLutNumValMinus1[c], 8, "m_postLutNumValMinus1[c]" ); if( sei.m_postLutNumValMinus1[c]>0 ) { for( Int i=0 ; i<=sei.m_postLutNumValMinus1[c] ; i++ ) { WRITE_CODE( sei.m_postLut[c][i].codedValue, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, "post_lut_coded_value[c][i]" ); WRITE_CODE( sei.m_postLut[c][i].targetValue, (( sei.m_colourRemapBitDepth + 7 ) >> 3 ) << 3, "post_lut_target_value[c][i]" ); } } } } } Void SEIWriter::xWriteSEIDeinterlaceFieldIdentification(const SEIDeinterlaceFieldIdentification& sei) { WRITE_FLAG( sei.m_deinterlacedPictureSourceParityFlag, "deinterlaced_picture_source_parity_flag" ); } Void SEIWriter::xWriteSEIContentLightLevelInfo(const SEIContentLightLevelInfo& sei) { WRITE_CODE( sei.m_maxContentLightLevel, 16, "max_content_light_level" ); WRITE_CODE( sei.m_maxPicAverageLightLevel, 16, "max_pic_average_light_level" ); } Void SEIWriter::xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& /*sei*/) { // intentionally empty } Void SEIWriter::xWriteSEICodedRegionCompletion(const SEICodedRegionCompletion& sei) { WRITE_UVLC( sei.m_nextSegmentAddress, "next_segment_address" ); if (sei.m_nextSegmentAddress) { WRITE_FLAG( sei.m_independentSliceSegmentFlag, "independent_slice_segment_flag" ); } } Void SEIWriter::xWriteSEIAlternativeTransferCharacteristics(const SEIAlternativeTransferCharacteristics& sei) { WRITE_CODE(sei.m_preferredTransferCharacteristics, 8, "preferred_transfer_characteristics"); } Void SEIWriter::xWriteSEIAmbientViewingEnvironment(const SEIAmbientViewingEnvironment& sei) { WRITE_CODE(sei.m_ambientIlluminance, 32, "ambient_illuminance" ); WRITE_CODE(sei.m_ambientLightX, 16, "ambient_light_x" ); WRITE_CODE(sei.m_ambientLightY, 16, "ambient_light_y" ); } Void SEIWriter::xWriteSEIRegionalNesting(TComBitIf& bs, const SEIRegionalNesting& sei, const TComSPS *sps) { WRITE_CODE(sei.getRNId(), 16, "regional_nesting_id"); WRITE_CODE(sei.getNumRectRegions(), 8, "regional_nesting_num_rect_regions"); const RNSEIWindowVec regions = sei.getRegions(); for(RNSEIWindowVec::const_iterator it = regions.begin(); it != regions.end(); it++) { assert((*it).getWindowEnabledFlag()); WRITE_CODE((*it).getRegionId(), 8, "regional_nesting_rect_region_id[i]"); WRITE_CODE((*it).getWindowLeftOffset(), 16, "regional_nesting_rect_left_offset[i]"); WRITE_CODE((*it).getWindowRightOffset(), 16, "regional_nesting_rect_right_offset[i]"); WRITE_CODE((*it).getWindowTopOffset(), 16, "regional_nesting_rect_top_offset[i]"); WRITE_CODE((*it).getWindowBottomOffset(), 16, "regional_nesting_rect_bottom_offset[i]"); } assert(sei.getNumRnSEIMessage() >= 1); WRITE_CODE(sei.getNumRnSEIMessage()-1, 8, "num_sei_messages_in_regional_nesting_minus1"); const std::vector seiMessages = sei.getRnSEIMessages(); std::vector::const_iterator it; for(it = seiMessages.begin(); it != seiMessages.end(); it++) { std::vector listOfRegions = (*it).m_listOfIndices; SEI *nestedSEI = (*it).m_seiMessage; WRITE_CODE((UInt)listOfRegions.size(), 8, "num_regions_for_sei_message[i]"); for(Int j = 0; j < listOfRegions.size(); j++) { WRITE_CODE(listOfRegions[j], 8, "regional_nesting_sei_region_idx[i][j]"); } xWriteSEImessage(bs, nestedSEI, sps); } } Void SEIWriter::xWriteSEIAnnotatedRegions(const SEIAnnotatedRegions &sei, const TComSPS *sps) { WRITE_FLAG(sei.m_hdr.m_cancelFlag, "ar_cancel_flag"); if (!sei.m_hdr.m_cancelFlag) { WRITE_FLAG(sei.m_hdr.m_notOptimizedForViewingFlag, "ar_not_optimized_for_viewing_flag"); WRITE_FLAG(sei.m_hdr.m_trueMotionFlag, "ar_true_motion_flag"); WRITE_FLAG(sei.m_hdr.m_occludedObjectFlag, "ar_occluded_object_flag"); WRITE_FLAG(sei.m_hdr.m_partialObjectFlagPresentFlag, "ar_partial_object_flag_present_flag"); WRITE_FLAG(sei.m_hdr.m_objectLabelPresentFlag, "ar_object_label_present_flag"); WRITE_FLAG(sei.m_hdr.m_objectConfidenceInfoPresentFlag, "ar_object_confidence_info_present_flag"); if (sei.m_hdr.m_objectConfidenceInfoPresentFlag) { assert(sei.m_hdr.m_objectConfidenceLength <= 16 && sei.m_hdr.m_objectConfidenceLength>0); WRITE_CODE((sei.m_hdr.m_objectConfidenceLength - 1), 4, "ar_object_confidence_length_minus_1"); } if (sei.m_hdr.m_objectLabelPresentFlag) { WRITE_FLAG(sei.m_hdr.m_objectLabelLanguagePresentFlag, "ar_object_label_language_present_flag"); if (sei.m_hdr.m_objectLabelLanguagePresentFlag) { xWriteByteAlign(); assert(sei.m_hdr.m_annotatedRegionsObjectLabelLang.size()<256); for (UInt j = 0; j < sei.m_hdr.m_annotatedRegionsObjectLabelLang.size(); j++) { UChar ch = sei.m_hdr.m_annotatedRegionsObjectLabelLang[j]; WRITE_CODE(ch, 8, "ar_object_label_language"); } WRITE_CODE('\0', 8, "ar_label_language"); } } WRITE_UVLC((UInt)sei.m_annotatedLabels.size(), "ar_num_label_updates"); assert(sei.m_annotatedLabels.size()<256); for(auto it=sei.m_annotatedLabels.begin(); it!=sei.m_annotatedLabels.end(); it++) { assert(it->first < 256); WRITE_UVLC(it->first, "ar_label_idx[]"); const SEIAnnotatedRegions::AnnotatedRegionLabel &ar=it->second; WRITE_FLAG(!ar.labelValid, "ar_label_cancel_flag"); if (ar.labelValid) { xWriteByteAlign(); assert(ar.label.size()<256); for (UInt j = 0; j < ar.label.size(); j++) { UChar ch = ar.label[j]; WRITE_CODE(ch, 8, "ar_label[]"); } WRITE_CODE('\0', 8, "ar_label[]"); } } WRITE_UVLC((UInt)sei.m_annotatedRegions.size(), "ar_num_object_updates"); assert(sei.m_annotatedRegions.size()<256); for (auto it=sei.m_annotatedRegions.begin(); it!=sei.m_annotatedRegions.end(); it++) { const SEIAnnotatedRegions::AnnotatedRegionObject &ar = it->second; WRITE_UVLC(it->first, "ar_object_idx"); WRITE_FLAG(ar.objectCancelFlag, "ar_object_cancel_flag"); if (!ar.objectCancelFlag) { if (sei.m_hdr.m_objectLabelPresentFlag) { WRITE_FLAG(ar.objectLabelValid, "ar_object_label_update_flag"); if (ar.objectLabelValid) { assert(ar.objLabelIdx<256); WRITE_UVLC(ar.objLabelIdx, "ar_object_label_idx"); } } WRITE_FLAG(ar.boundingBoxValid, "ar_object_bounding_box_update_flag"); if (ar.boundingBoxValid) { WRITE_FLAG(ar.boundingBoxCancelFlag, "ar_object_bounding_box_cancel_flag"); if (!ar.boundingBoxCancelFlag) { WRITE_CODE(ar.boundingBoxTop, 16, "ar_bounding_box_top"); WRITE_CODE(ar.boundingBoxLeft, 16, "ar_bounding_box_left"); WRITE_CODE(ar.boundingBoxWidth, 16, "ar_bounding_box_width"); WRITE_CODE(ar.boundingBoxHeight,16, "ar_bounding_box_height"); if (sei.m_hdr.m_partialObjectFlagPresentFlag) { WRITE_UVLC(ar.partialObjectFlag, "ar_partial_object_flag"); } if (sei.m_hdr.m_objectConfidenceInfoPresentFlag) { assert(ar.objectConfidence < (1<(sei.m_payload), sps, idx); xWriteSEIPrefixIndicationByteAlign(); } Void SEIWriter::xWriteSEIPrefixIndicationByteAlign() { while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) { WRITE_FLAG(1, "byte_alignment_bit_equal_to_one"); } } // ~SEI prefix indication #endif Void SEIWriter::xWriteByteAlign() { if (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) { WRITE_FLAG(1, "payload_bit_equal_to_one"); while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) { WRITE_FLAG(0, "payload_bit_equal_to_zero"); } } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/SEIwrite.h000066400000000000000000000174121442026013100202520ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #ifndef __SEIWRITE__ #define __SEIWRITE__ #include "SyntaxElementWriter.h" #include "TLibCommon/SEI.h" class TComBitIf; //! \ingroup TLibEncoder //! \{ class SEIWriter:public SyntaxElementWriter { public: SEIWriter() {}; virtual ~SEIWriter() {}; Void writeSEImessages(TComBitIf& bs, const SEIMessages &seiList, const TComSPS *sps, Bool isNested); protected: Void xWriteSEImessage (TComBitIf& bs, const SEI *sei, const TComSPS *sps); Void xWriteSEIBufferingPeriod (const SEIBufferingPeriod& sei, const TComSPS *sps); Void xWriteSEIPictureTiming (const SEIPictureTiming& sei, const TComSPS *sps); Void xWriteSEIPanScanRect (const SEIPanScanRect& sei); Void xWriteSEIFillerPayload (const SEIFillerPayload& sei); Void xWriteSEIUserDataRegistered (const SEIUserDataRegistered& sei); Void xWriteSEIUserDataUnregistered (const SEIUserDataUnregistered &sei); Void xWriteSEIRecoveryPoint (const SEIRecoveryPoint& sei); Void xWriteSEISceneInfo (const SEISceneInfo& sei); Void xWriteSEIPictureSnapshot (const SEIPictureSnapshot& sei); Void xWriteSEIProgressiveRefinementSegmentStart (const SEIProgressiveRefinementSegmentStart& sei); Void xWriteSEIProgressiveRefinementSegmentEnd (const SEIProgressiveRefinementSegmentEnd& sei); Void xWriteSEIFilmGrainCharacteristics (const SEIFilmGrainCharacteristics& sei); Void xWriteSEIPostFilterHint (const SEIPostFilterHint& sei, const TComSPS *sps); Void xWriteSEIToneMappingInfo (const SEIToneMappingInfo& sei); Void xWriteSEIFramePacking (const SEIFramePacking& sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx = 0 #endif ); Void xWriteSEIDisplayOrientation (const SEIDisplayOrientation &sei); Void xWriteSEIGreenMetadataInfo (const SEIGreenMetadataInfo &sei); Void xWriteSEISOPDescription (const SEISOPDescription& sei); Void xWriteSEIActiveParameterSets (const SEIActiveParameterSets& sei); Void xWriteSEIDecodingUnitInfo (const SEIDecodingUnitInfo& sei, const TComSPS *sps); Void xWriteSEITemporalLevel0Index (const SEITemporalLevel0Index &sei); Void xWriteSEIDecodedPictureHash (const SEIDecodedPictureHash& sei); Void xWriteSEIScalableNesting (TComBitIf& bs, const SEIScalableNesting& sei, const TComSPS *sps); Void xWriteSEIRegionRefreshInfo (const SEIRegionRefreshInfo &sei); Void xWriteSEINoDisplay (const SEINoDisplay &sei); Void xWriteSEITimeCode (const SEITimeCode& sei); Void xWriteSEIMasteringDisplayColourVolume (const SEIMasteringDisplayColourVolume& sei); Void xWriteSEISegmentedRectFramePacking (const SEISegmentedRectFramePacking& sei); Void xWriteSEITempMotionConstrainedTileSets (const SEITempMotionConstrainedTileSets& sei); #if MCTS_EXTRACTION Void xWriteSEIMCTSExtractionInfoSet (const SEIMCTSExtractionInfoSet& sei); #endif Void xWriteSEIChromaResamplingFilterHint (const SEIChromaResamplingFilterHint& sei); Void xWriteSEIKneeFunctionInfo (const SEIKneeFunctionInfo &sei); Void xWriteSEIContentColourVolume (const SEIContentColourVolume &sei); Void xWriteSEIEquirectangularProjection (const SEIEquirectangularProjection &sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx = 0 #endif ); Void xWriteSEISphereRotation (const SEISphereRotation &sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx = 0 #endif ); Void xWriteSEIOmniViewport (const SEIOmniViewport& sei); Void xWriteSEICubemapProjection (const SEICubemapProjection &sei); Void xWriteSEIRegionWisePacking (const SEIRegionWisePacking &sei #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx = 0 #endif ); Void xWriteSEIFisheyeVideoInfo (const SEIFisheyeVideoInfo &sei); Void xWriteSEIColourRemappingInfo (const SEIColourRemappingInfo& sei); Void xWriteSEIDeinterlaceFieldIdentification (const SEIDeinterlaceFieldIdentification& sei); Void xWriteSEIContentLightLevelInfo (const SEIContentLightLevelInfo& sei); Void xWriteSEIDependentRAPIndication (const SEIDependentRAPIndication& sei); Void xWriteSEICodedRegionCompletion (const SEICodedRegionCompletion& sei); Void xWriteSEIAlternativeTransferCharacteristics(const SEIAlternativeTransferCharacteristics& sei); Void xWriteSEIAmbientViewingEnvironment (const SEIAmbientViewingEnvironment& sei); Void xWriteSEIRegionalNesting (TComBitIf& bs, const SEIRegionalNesting& sei, const TComSPS *sps); Void xWriteSEIAnnotatedRegions (const SEIAnnotatedRegions& sei, const TComSPS *sps); #if JCTVC_AD0021_SEI_MANIFEST //SEI manifest Void xWriteSEISEIManifest(const SEIManifest& sei); #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION //SEI prefix indication Void xWriteSEISEIPrefixIndication(TComBitIf& bs, const SEIPrefixIndication& sei, const TComSPS* sps); Void xWriteSEIPrefixIndicationByteAlign(); UInt getBitsUe(UInt x) { UInt n = 0; x += 1; for (Int s = 4; s >= 0; s--) { Int b = 1 << s; UInt m = (1u << b) - 1u; if ((x & ~m) != 0) { x >>= b; n += b; } } return 2 * n + 1; } #endif #if SHUTTER_INTERVAL_SEI_MESSAGE Void xWriteSEIShutterInterval (const SEIShutterIntervalInfo& sei); #endif Void xWriteSEIpayloadData(TComBitIf& bs, const SEI& sei, const TComSPS *sps #if JCTVC_AD0021_SEI_PREFIX_INDICATION , Int SEIPrefixIndicationIdx = 0 #endif ); Void xWriteByteAlign(); }; //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/SyntaxElementWriter.cpp000066400000000000000000000114661442026013100231120ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SyntaxElementWriter.cpp \brief CAVLC encoder class */ #include "TLibCommon/CommonDef.h" #include "SyntaxElementWriter.h" //! \ingroup TLibEncoder //! \{ #if ENC_DEC_TRACE Void SyntaxElementWriter::xWriteSCodeTr (Int value, UInt length, const TChar *pSymbolName) { xWriteSCode (value,length); if( g_HLSTraceEnable ) { fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); if( length<10 ) { fprintf( g_hTrace, "%-50s u(%d) : %d\n", pSymbolName, length, value ); } else { fprintf( g_hTrace, "%-50s u(%d) : %d\n", pSymbolName, length, value ); } } } Void SyntaxElementWriter::xWriteCodeTr (UInt value, UInt length, const TChar *pSymbolName) { xWriteCode (value,length); if( g_HLSTraceEnable ) { fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); if( length<10 ) { fprintf( g_hTrace, "%-50s u(%d) : %d\n", pSymbolName, length, value ); } else { fprintf( g_hTrace, "%-50s u(%d) : %d\n", pSymbolName, length, value ); } } } Void SyntaxElementWriter::xWriteUvlcTr (UInt value, const TChar *pSymbolName) { xWriteUvlc (value); if( g_HLSTraceEnable ) { fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s ue(v) : %d\n", pSymbolName, value ); } } Void SyntaxElementWriter::xWriteSvlcTr (Int value, const TChar *pSymbolName) { xWriteSvlc(value); if( g_HLSTraceEnable ) { fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s se(v) : %d\n", pSymbolName, value ); } } Void SyntaxElementWriter::xWriteFlagTr(UInt value, const TChar *pSymbolName) { xWriteFlag(value); if( g_HLSTraceEnable ) { fprintf( g_hTrace, "%8lld ", g_nSymbolCounter++ ); fprintf( g_hTrace, "%-50s u(1) : %d\n", pSymbolName, value ); } } #endif Void SyntaxElementWriter::xWriteSCode ( Int iCode, UInt uiLength ) { assert ( uiLength > 0 && uiLength<=32 ); assert( uiLength==32 || (iCode>=-(1<<(uiLength-1)) && iCode<(1<<(uiLength-1))) ); m_pcBitIf->write( uiLength==32 ? UInt(iCode) : ( UInt(iCode)&((1< 0 ); m_pcBitIf->write( uiCode, uiLength ); } Void SyntaxElementWriter::xWriteUvlc ( UInt uiCode ) { UInt uiLength = 1; UInt uiTemp = ++uiCode; assert ( uiTemp ); while( 1 != uiTemp ) { uiTemp >>= 1; uiLength += 2; } // Take care of cases where uiLength > 32 m_pcBitIf->write( 0, uiLength >> 1); m_pcBitIf->write( uiCode, (uiLength+1) >> 1); } Void SyntaxElementWriter::xWriteSvlc ( Int iCode ) { UInt uiCode; uiCode = xConvertToUInt( iCode ); xWriteUvlc( uiCode ); } Void SyntaxElementWriter::xWriteFlag( UInt uiCode ) { m_pcBitIf->write( uiCode, 1 ); } Void SyntaxElementWriter::xWriteRbspTrailingBits() { WRITE_FLAG( 1, "rbsp_stop_one_bit"); Int cnt = 0; while (m_pcBitIf->getNumBitsUntilByteAligned()) { WRITE_FLAG( 0, "rbsp_alignment_zero_bit"); cnt++; } assert(cnt<8); } //! \} HM-HM-18.0/source/Lib/TLibEncoder/SyntaxElementWriter.h000066400000000000000000000100131442026013100225420ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file SyntaxElementWriter.h \brief CAVLC encoder class (header) */ #ifndef __SYNTAXELEMENTWRITER__ #define __SYNTAXELEMENTWRITER__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/TComRom.h" //! \ingroup TLibEncoder //! \{ #if ENC_DEC_TRACE #define WRITE_SCODE( value, length, name) xWriteSCodeTr ( value, length, name ) #define WRITE_CODE( value, length, name) xWriteCodeTr ( value, length, name ) #define WRITE_UVLC( value, name) xWriteUvlcTr ( value, name ) #define WRITE_SVLC( value, name) xWriteSvlcTr ( value, name ) #define WRITE_FLAG( value, name) xWriteFlagTr ( value, name ) #else #define WRITE_SCODE( value, length, name) xWriteSCode ( value, length ) #define WRITE_CODE( value, length, name) xWriteCode ( value, length ) #define WRITE_UVLC( value, name) xWriteUvlc ( value ) #define WRITE_SVLC( value, name) xWriteSvlc ( value ) #define WRITE_FLAG( value, name) xWriteFlag ( value ) #endif class SyntaxElementWriter { protected: TComBitIf* m_pcBitIf; SyntaxElementWriter() :m_pcBitIf(NULL) {}; virtual ~SyntaxElementWriter() {}; Void setBitstream ( TComBitIf* p ) { m_pcBitIf = p; } Void xWriteSCode ( Int iCode, UInt uiLength ); Void xWriteCode ( UInt uiCode, UInt uiLength ); Void xWriteUvlc ( UInt uiCode ); Void xWriteSvlc ( Int iCode ); Void xWriteFlag ( UInt uiCode ); #if ENC_DEC_TRACE Void xWriteSCodeTr ( Int value, UInt length, const TChar *pSymbolName); Void xWriteCodeTr ( UInt value, UInt length, const TChar *pSymbolName); Void xWriteUvlcTr ( UInt value, const TChar *pSymbolName); Void xWriteSvlcTr ( Int value, const TChar *pSymbolName); Void xWriteFlagTr ( UInt value, const TChar *pSymbolName); #endif Void xWriteRbspTrailingBits(); UInt xConvertToUInt ( Int iValue ) { return ( iValue <= 0) ? -iValue<<1 : (iValue<<1)-1; } }; //! \} #endif // !defined(__SYNTAXELEMENTWRITER__) HM-HM-18.0/source/Lib/TLibEncoder/TEncAnalyze.h000066400000000000000000000327761442026013100207460ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncAnalyze.h \brief encoder analyzer class (header) */ #ifndef __TENCANALYZE__ #define __TENCANALYZE__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComChromaFormat.h" #include "math.h" #if EXTENSION_360_VIDEO #include "TAppEncHelper360/TExt360EncAnalyze.h" #endif //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// encoder analyzer class class TEncAnalyze { public: struct OutputLogControl { Bool printMSEBasedSNR; Bool printSequenceMSE; Bool printFrameMSE; Bool printMSSSIM; Bool printXPSNR; Bool printHexPerPOCPSNRs; }; struct ResultData { ResultData () : bits(0) , xpsnr(0) { for(Int i=0; i maximumBitDepth) { maximumBitDepth = bitDepths.recon[channelTypeIndex]; } } const UInt maxval = 255 << (maximumBitDepth - 8); const UInt numberValidComponents = getNumberValidComponents(chFmt); for (UInt comp=0; comp>(csx+csy)); const UInt bitDepthShift = 2 * (maximumBitDepth - bitDepths.recon[toChannelType(compID)]); //*2 because this is a squared number const Double channelMSE = (m_runningTotal.MSEyuvframe[compID] * Double(1 << bitDepthShift)) / Double(getNumPic()); scale += scaleChan; MSEyuv += scaleChan * channelMSE; } MSEyuv /= Double(scale); // i.e. divide by 6 for 4:2:0, 8 for 4:2:2 etc. PSNRyuv = (MSEyuv==0 ? 999.99 : 10*log10((maxval*maxval)/MSEyuv)); } Void printOut ( TChar cDelim, const ChromaFormat chFmt, const OutputLogControl &logctrl, const BitDepths &bitDepths ) { Double dFps = m_dFrmRate; //--CFG_KDY Double dScale = dFps / 1000 / (Double)m_uiNumPic; Double MSEBasedSNR[MAX_NUM_COMPONENT]; if (logctrl.printMSEBasedSNR) { for (UInt componentIndex = 0; componentIndex < MAX_NUM_COMPONENT; componentIndex++) { const ComponentID compID = ComponentID(componentIndex); if (getNumPic() == 0) { MSEBasedSNR[compID] = 0 * dScale; // this is the same calculation that will be evaluated for any other statistic when there are no frames (it should result in NaN). We use it here so all the output is consistent. } else { //NOTE: this is not the true maximum value for any bitDepth other than 8. It comes from the original HM PSNR calculation const UInt maxval = 255 << (bitDepths.recon[toChannelType(compID)] - 8); const Double MSE = m_runningTotal.MSEyuvframe[compID]; MSEBasedSNR[compID] = (MSE == 0) ? 999.99 : (10 * log10((maxval * maxval) / (MSE / (Double)getNumPic()))); } } } switch (chFmt) { case CHROMA_400: if (logctrl.printMSEBasedSNR) { printf( " " ); } printf( "\tTotal Frames | " "Bitrate " "Y-PSNR " ); if (logctrl.printMSSSIM) { printf( " Y-MS-SSIM "); } if (logctrl.printXPSNR) { printf( " xPSNR "); } if (logctrl.printSequenceMSE) { printf( " Y-MSE \n" ); } else { printf("\n"); } if (logctrl.printMSEBasedSNR) { printf( "Average: "); } printf( "\t %8d %c " "%12.4lf " "%8.4lf ", getNumPic(), cDelim, getBits() * dScale, getPsnr(COMPONENT_Y) / (Double)getNumPic() ); if (logctrl.printMSSSIM) { printf(" %8.6lf ", getMsssim(COMPONENT_Y) / (Double)getNumPic()); } if(logctrl.printXPSNR) { printf(" %8.4lf ", getxPSNR() / (Double)getNumPic()); } if (logctrl.printSequenceMSE) { printf( " %8.4lf \n", m_runningTotal.MSEyuvframe[COMPONENT_Y ] / (Double)getNumPic() ); } else { printf("\n"); } if (logctrl.printMSEBasedSNR) { printf( "From MSE:\t %8d %c " "%12.4lf " "%8.4lf\n", getNumPic(), cDelim, getBits() * dScale, MSEBasedSNR[COMPONENT_Y] ); } break; case CHROMA_420: case CHROMA_422: case CHROMA_444: { Double PSNRyuv = MAX_DOUBLE; Double MSEyuv = MAX_DOUBLE; calculateCombinedValues(chFmt, PSNRyuv, MSEyuv, bitDepths); if (logctrl.printMSEBasedSNR) { printf( " " ); } printf( "\tTotal Frames | " "Bitrate " "Y-PSNR " "U-PSNR " "V-PSNR " "YUV-PSNR " ); if (logctrl.printMSSSIM) { printf(" Y-MS-SSIM " "U-MS-SSIM " "V-MS-SSIM "); } if (logctrl.printXPSNR) { printf( " xPSNR "); } #if EXTENSION_360_VIDEO m_ext360.printHeader(); #endif if (logctrl.printSequenceMSE) { printf( " Y-MSE " "U-MSE " "V-MSE " "YUV-MSE \n" ); } else { printf("\n"); } if (logctrl.printMSEBasedSNR) { printf( "Average: "); } printf( "\t %8d %c " "%12.4lf " "%8.4lf " "%8.4lf " "%8.4lf " "%8.4lf ", getNumPic(), cDelim, getBits() * dScale, getPsnr(COMPONENT_Y) / (Double)getNumPic(), getPsnr(COMPONENT_Cb) / (Double)getNumPic(), getPsnr(COMPONENT_Cr) / (Double)getNumPic(), PSNRyuv ); if (logctrl.printMSSSIM) { printf(" %8.6lf " "%8.6lf " "%8.6lf ", getMsssim(COMPONENT_Y) / (Double)getNumPic(), getMsssim(COMPONENT_Cb) / (Double)getNumPic(), getMsssim(COMPONENT_Cr) / (Double)getNumPic()); } if(logctrl.printXPSNR) { printf(" %8.4lf ", getxPSNR() / (Double)getNumPic()); } #if EXTENSION_360_VIDEO m_ext360.printPSNRs(getNumPic()); #endif if (logctrl.printSequenceMSE) { printf( " %8.4lf " "%8.4lf " "%8.4lf " "%8.4lf \n", m_runningTotal.MSEyuvframe[COMPONENT_Y ] / (Double)getNumPic(), m_runningTotal.MSEyuvframe[COMPONENT_Cb] / (Double)getNumPic(), m_runningTotal.MSEyuvframe[COMPONENT_Cr] / (Double)getNumPic(), MSEyuv ); } else { printf("\n"); } if (logctrl.printMSEBasedSNR) { printf( "From MSE:\t %8d %c " "%12.4lf " "%8.4lf " "%8.4lf " "%8.4lf " "%8.4lf\n", getNumPic(), cDelim, getBits() * dScale, MSEBasedSNR[COMPONENT_Y], MSEBasedSNR[COMPONENT_Cb], MSEBasedSNR[COMPONENT_Cr], PSNRyuv ); } } break; default: fprintf(stderr, "Unknown format during print out\n"); exit(1); break; } } Void printSummary(const ChromaFormat chFmt, const OutputLogControl &logctrl, const BitDepths &bitDepths, const std::string &sFilename) { FILE* pFile = fopen (sFilename.c_str(), "at"); Double dFps = m_dFrmRate; //--CFG_KDY Double dScale = dFps / 1000 / (Double)m_uiNumPic; switch (chFmt) { case CHROMA_400: fprintf(pFile, "%f\t %f\n", getBits() * dScale, getPsnr(COMPONENT_Y) / (Double)getNumPic() ); break; case CHROMA_420: case CHROMA_422: case CHROMA_444: { Double PSNRyuv = MAX_DOUBLE; Double MSEyuv = MAX_DOUBLE; calculateCombinedValues(chFmt, PSNRyuv, MSEyuv, bitDepths); fprintf(pFile, "%f\t %f\t %f\t %f\t %f", getBits() * dScale, getPsnr(COMPONENT_Y) / (Double)getNumPic(), getPsnr(COMPONENT_Cb) / (Double)getNumPic(), getPsnr(COMPONENT_Cr) / (Double)getNumPic(), PSNRyuv ); if (logctrl.printSequenceMSE) { fprintf(pFile, "\t %f\t %f\t %f\t %f\n", m_runningTotal.MSEyuvframe[COMPONENT_Y ] / (Double)getNumPic(), m_runningTotal.MSEyuvframe[COMPONENT_Cb] / (Double)getNumPic(), m_runningTotal.MSEyuvframe[COMPONENT_Cr] / (Double)getNumPic(), MSEyuv ); } else { fprintf(pFile, "\n"); } break; } default: fprintf(stderr, "Unknown format during print out\n"); exit(1); break; } fclose(pFile); } }; extern TEncAnalyze m_gcAnalyzeAll; extern TEncAnalyze m_gcAnalyzeI; extern TEncAnalyze m_gcAnalyzeP; extern TEncAnalyze m_gcAnalyzeB; extern TEncAnalyze m_gcAnalyzeAll_in; //! \} #endif // !defined(AFX_TENCANALYZE_H__C79BCAA2_6AC8_4175_A0FE_CF02F5829233__INCLUDED_) HM-HM-18.0/source/Lib/TLibEncoder/TEncBinCoder.h000066400000000000000000000070651442026013100210210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncBinCoder.h \brief binary entropy encoder interface */ #ifndef __TENCBINCODER__ #define __TENCBINCODER__ #include "TLibCommon/ContextModel.h" #include "TLibCommon/TComBitStream.h" //! \ingroup TLibEncoder //! \{ class TEncBinCABAC; class TEncBinIf { public: virtual Void init ( TComBitIf* pcTComBitIf ) = 0; virtual Void uninit () = 0; virtual Void start () = 0; virtual Void finish () = 0; virtual Void copyState ( const TEncBinIf* pcTEncBinIf ) = 0; virtual Void flush () = 0; virtual Void resetBac () = 0; virtual Void encodePCMAlignBits() = 0; virtual Void xWritePCMCode ( UInt uiCode, UInt uiLength ) = 0; virtual Void resetBits () = 0; virtual UInt getNumWrittenBits () = 0; virtual Void encodeBin ( UInt uiBin, ContextModel& rcCtxModel ) = 0; virtual Void encodeBinEP ( UInt uiBin ) = 0; virtual Void encodeBinsEP ( UInt uiBins, Int numBins ) = 0; virtual Void encodeBinTrm ( UInt uiBin ) = 0; virtual Void align () = 0; virtual TEncBinCABAC* getTEncBinCABAC () { return 0; } virtual const TEncBinCABAC* getTEncBinCABAC () const { return 0; } virtual ~TEncBinIf() {} }; //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncBinCoderCABAC.cpp000066400000000000000000000240611442026013100220610ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncBinCoderCABAC.cpp \brief binary entropy encoder of CABAC */ #include "TEncBinCoderCABAC.h" #include "TLibCommon/TComRom.h" #include "TLibCommon/Debug.h" //! \ingroup TLibEncoder //! \{ TEncBinCABAC::TEncBinCABAC() : m_pcTComBitIf( 0 ) , m_binCountIncrement( 0 ) #if FAST_BIT_EST , m_fracBits( 0 ) #endif { } TEncBinCABAC::~TEncBinCABAC() { } Void TEncBinCABAC::init( TComBitIf* pcTComBitIf ) { m_pcTComBitIf = pcTComBitIf; } Void TEncBinCABAC::uninit() { m_pcTComBitIf = 0; } Void TEncBinCABAC::start() { m_uiLow = 0; m_uiRange = 510; m_bitsLeft = 23; m_numBufferedBytes = 0; m_bufferedByte = 0xff; #if FAST_BIT_EST m_fracBits = 0; #endif } Void TEncBinCABAC::finish() { if ( m_uiLow >> ( 32 - m_bitsLeft ) ) { //assert( m_numBufferedBytes > 0 ); //assert( m_bufferedByte != 0xff ); m_pcTComBitIf->write( m_bufferedByte + 1, 8 ); while ( m_numBufferedBytes > 1 ) { m_pcTComBitIf->write( 0x00, 8 ); m_numBufferedBytes--; } m_uiLow -= 1 << ( 32 - m_bitsLeft ); } else { if ( m_numBufferedBytes > 0 ) { m_pcTComBitIf->write( m_bufferedByte, 8 ); } while ( m_numBufferedBytes > 1 ) { m_pcTComBitIf->write( 0xff, 8 ); m_numBufferedBytes--; } } m_pcTComBitIf->write( m_uiLow >> 8, 24 - m_bitsLeft ); } Void TEncBinCABAC::flush() { encodeBinTrm(1); finish(); m_pcTComBitIf->write(1, 1); m_pcTComBitIf->writeAlignZero(); start(); } /** Reset BAC register and counter values. * \returns Void */ Void TEncBinCABAC::resetBac() { start(); } /** Encode PCM alignment zero bits. * \returns Void */ Void TEncBinCABAC::encodePCMAlignBits() { finish(); m_pcTComBitIf->write(1, 1); m_pcTComBitIf->writeAlignZero(); // pcm align zero } /** Write a PCM code. * \param uiCode code value * \param uiLength code bit-depth * \returns Void */ Void TEncBinCABAC::xWritePCMCode(UInt uiCode, UInt uiLength) { m_pcTComBitIf->write(uiCode, uiLength); } Void TEncBinCABAC::copyState( const TEncBinIf* pcTEncBinIf ) { const TEncBinCABAC* pcTEncBinCABAC = pcTEncBinIf->getTEncBinCABAC(); m_uiLow = pcTEncBinCABAC->m_uiLow; m_uiRange = pcTEncBinCABAC->m_uiRange; m_bitsLeft = pcTEncBinCABAC->m_bitsLeft; m_bufferedByte = pcTEncBinCABAC->m_bufferedByte; m_numBufferedBytes = pcTEncBinCABAC->m_numBufferedBytes; #if FAST_BIT_EST m_fracBits = pcTEncBinCABAC->m_fracBits; #endif } Void TEncBinCABAC::resetBits() { m_uiLow = 0; m_bitsLeft = 23; m_numBufferedBytes = 0; m_bufferedByte = 0xff; if ( m_binCountIncrement ) { m_uiBinsCoded = 0; } #if FAST_BIT_EST m_fracBits &= 32767; #endif } UInt TEncBinCABAC::getNumWrittenBits() { return m_pcTComBitIf->getNumberOfWrittenBits() + 8 * m_numBufferedBytes + 23 - m_bitsLeft; } /** * \brief Encode bin * * \param binValue bin value * \param rcCtxModel context model */ Void TEncBinCABAC::encodeBin( UInt binValue, ContextModel &rcCtxModel ) { //{ // DTRACE_CABAC_VL( g_nSymbolCounter++ ) // DTRACE_CABAC_T( "\tstate=" ) // DTRACE_CABAC_V( ( rcCtxModel.getState() << 1 ) + rcCtxModel.getMps() ) // DTRACE_CABAC_T( "\tsymbol=" ) // DTRACE_CABAC_V( binValue ) // DTRACE_CABAC_T( "\n" ) //} #if DEBUG_CABAC_BINS const UInt startingRange = m_uiRange; #endif m_uiBinsCoded += m_binCountIncrement; rcCtxModel.setBinsCoded( 1 ); UInt uiLPS = TComCABACTables::sm_aucLPSTable[ rcCtxModel.getState() ][ ( m_uiRange >> 6 ) & 3 ]; m_uiRange -= uiLPS; if( binValue != rcCtxModel.getMps() ) { Int numBits = TComCABACTables::sm_aucRenormTable[ uiLPS >> 3 ]; m_uiLow = ( m_uiLow + m_uiRange ) << numBits; m_uiRange = uiLPS << numBits; rcCtxModel.updateLPS(); m_bitsLeft -= numBits; testAndWriteOut(); } else { rcCtxModel.updateMPS(); if ( m_uiRange < 256 ) { m_uiLow <<= 1; m_uiRange <<= 1; m_bitsLeft--; testAndWriteOut(); } } #if DEBUG_CABAC_BINS if ((g_debugCounter + debugCabacBinWindow) >= debugCabacBinTargetLine) { std::cout << g_debugCounter << ": coding bin value " << binValue << ", range = [" << startingRange << "->" << m_uiRange << "]\n"; } if (g_debugCounter >= debugCabacBinTargetLine) { UChar breakPointThis; breakPointThis = 7; } if (g_debugCounter >= (debugCabacBinTargetLine + debugCabacBinWindow)) { exit(0); } g_debugCounter++; #endif } /** * \brief Encode equiprobable bin * * \param binValue bin value */ Void TEncBinCABAC::encodeBinEP( UInt binValue ) { if (false) { DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tEPsymbol=" ) DTRACE_CABAC_V( binValue ) DTRACE_CABAC_T( "\n" ) } m_uiBinsCoded += m_binCountIncrement; if (m_uiRange == 256) { encodeAlignedBinsEP(binValue, 1); return; } m_uiLow <<= 1; if( binValue ) { m_uiLow += m_uiRange; } m_bitsLeft--; testAndWriteOut(); } /** * \brief Encode equiprobable bins * * \param binValues bin values * \param numBins number of bins */ Void TEncBinCABAC::encodeBinsEP( UInt binValues, Int numBins ) { m_uiBinsCoded += numBins & -m_binCountIncrement; if (false) { for ( Int i = 0; i < numBins; i++ ) { DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tEPsymbol=" ) DTRACE_CABAC_V( ( binValues >> ( numBins - 1 - i ) ) & 1 ) DTRACE_CABAC_T( "\n" ) } } if (m_uiRange == 256) { encodeAlignedBinsEP(binValues, numBins); return; } while ( numBins > 8 ) { numBins -= 8; UInt pattern = binValues >> numBins; m_uiLow <<= 8; m_uiLow += m_uiRange * pattern; binValues -= pattern << numBins; m_bitsLeft -= 8; testAndWriteOut(); } m_uiLow <<= numBins; m_uiLow += m_uiRange * binValues; m_bitsLeft -= numBins; testAndWriteOut(); } Void TEncBinCABAC::align() { m_uiRange = 256; } Void TEncBinCABAC::encodeAlignedBinsEP( UInt binValues, Int numBins ) { Int binsRemaining = numBins; assert(m_uiRange == 256); //aligned encode only works when range = 256 while (binsRemaining > 0) { const UInt binsToCode = std::min(binsRemaining, 8); //code bytes if able to take advantage of the system's byte-write function const UInt binMask = (1 << binsToCode) - 1; const UInt newBins = (binValues >> (binsRemaining - binsToCode)) & binMask; //The process of encoding an EP bin is the same as that of coding a normal //bin where the symbol ranges for 1 and 0 are both half the range: // // low = (low + range/2) << 1 (to encode a 1) // low = low << 1 (to encode a 0) // // i.e. // low = (low + (bin * range/2)) << 1 // // which is equivalent to: // // low = (low << 1) + (bin * range) // // this can be generalised for multiple bins, producing the following expression: // m_uiLow = (m_uiLow << binsToCode) + (newBins << 8); //range is known to be 256 binsRemaining -= binsToCode; m_bitsLeft -= binsToCode; testAndWriteOut(); } } /** * \brief Encode terminating bin * * \param binValue bin value */ Void TEncBinCABAC::encodeBinTrm( UInt binValue ) { m_uiBinsCoded += m_binCountIncrement; m_uiRange -= 2; if( binValue ) { m_uiLow += m_uiRange; m_uiLow <<= 7; m_uiRange = 2 << 7; m_bitsLeft -= 7; } else if ( m_uiRange >= 256 ) { return; } else { m_uiLow <<= 1; m_uiRange <<= 1; m_bitsLeft--; } testAndWriteOut(); } Void TEncBinCABAC::testAndWriteOut() { if ( m_bitsLeft < 12 ) { writeOut(); } } /** * \brief Move bits from register into bitstream */ Void TEncBinCABAC::writeOut() { UInt leadByte = m_uiLow >> (24 - m_bitsLeft); m_bitsLeft += 8; m_uiLow &= 0xffffffffu >> m_bitsLeft; if ( leadByte == 0xff ) { m_numBufferedBytes++; } else { if ( m_numBufferedBytes > 0 ) { UInt carry = leadByte >> 8; UInt byte = m_bufferedByte + carry; m_bufferedByte = leadByte & 0xff; m_pcTComBitIf->write( byte, 8 ); byte = ( 0xff + carry ) & 0xff; while ( m_numBufferedBytes > 1 ) { m_pcTComBitIf->write( byte, 8 ); m_numBufferedBytes--; } } else { m_numBufferedBytes = 1; m_bufferedByte = leadByte; } } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncBinCoderCABAC.h000066400000000000000000000075231442026013100215320ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncBinCoderCABAC.h \brief binary entropy encoder of CABAC */ #ifndef __TENCBINCODERCABAC__ #define __TENCBINCODERCABAC__ #include "TLibCommon/TComCABACTables.h" #include "TEncBinCoder.h" //! \ingroup TLibEncoder //! \{ class TEncBinCABAC : public TEncBinIf { public: TEncBinCABAC (); virtual ~TEncBinCABAC(); Void init ( TComBitIf* pcTComBitIf ); Void uninit (); Void start (); Void finish (); Void copyState ( const TEncBinIf* pcTEncBinIf ); Void flush (); Void resetBac (); Void encodePCMAlignBits(); Void xWritePCMCode ( UInt uiCode, UInt uiLength ); Void resetBits (); UInt getNumWrittenBits (); Void encodeBin ( UInt binValue, ContextModel& rcCtxModel ); Void encodeBinEP ( UInt binValue ); Void encodeBinsEP ( UInt binValues, Int numBins ); Void encodeBinTrm ( UInt binValue ); Void align (); Void encodeAlignedBinsEP( UInt binValues, Int numBins ); TEncBinCABAC* getTEncBinCABAC() { return this; } const TEncBinCABAC* getTEncBinCABAC() const { return this; } Void setBinsCoded ( UInt uiVal ) { m_uiBinsCoded = uiVal; } UInt getBinsCoded () { return m_uiBinsCoded; } Void setBinCountingEnableFlag ( Bool bFlag ) { m_binCountIncrement = bFlag ? 1 : 0; } Bool getBinCountingEnableFlag () { return m_binCountIncrement != 0; } #if FAST_BIT_EST protected: #else private: #endif Void testAndWriteOut(); Void writeOut(); TComBitIf* m_pcTComBitIf; UInt m_uiLow; UInt m_uiRange; UInt m_bufferedByte; Int m_numBufferedBytes; Int m_bitsLeft; UInt m_uiBinsCoded; Int m_binCountIncrement; #if FAST_BIT_EST UInt64 m_fracBits; #endif }; //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncBinCoderCABACCounter.cpp000066400000000000000000000100551442026013100234170ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncBinCoderCABAC.cpp \brief binary entropy encoder of CABAC */ #include "TEncBinCoderCABACCounter.h" #include "TLibCommon/TComRom.h" #include "TLibCommon/Debug.h" #if FAST_BIT_EST //! \ingroup TLibEncoder //! \{ TEncBinCABACCounter::TEncBinCABACCounter() { } TEncBinCABACCounter::~TEncBinCABACCounter() { } Void TEncBinCABACCounter::finish() { m_pcTComBitIf->write(0, UInt(m_fracBits >> 15) ); m_fracBits &= 32767; } UInt TEncBinCABACCounter::getNumWrittenBits() { return m_pcTComBitIf->getNumberOfWrittenBits() + UInt( m_fracBits >> 15 ); } /** * \brief Encode bin * * \param binValue bin value * \param rcCtxModel context model */ Void TEncBinCABACCounter::encodeBin( UInt binValue, ContextModel &rcCtxModel ) { #if DEBUG_ENCODER_SEARCH_BINS const UInt64 startingFracBits = m_fracBits; #endif m_uiBinsCoded += m_binCountIncrement; m_fracBits += rcCtxModel.getEntropyBits( binValue ); rcCtxModel.update( binValue ); #if DEBUG_ENCODER_SEARCH_BINS if ((g_debugCounter + debugEncoderSearchBinWindow) >= debugEncoderSearchBinTargetLine) { std::cout << g_debugCounter << ": coding bin value " << binValue << ", fracBits = [" << startingFracBits << "->" << m_fracBits << "]\n"; } if (g_debugCounter >= debugEncoderSearchBinTargetLine) { UChar breakPointThis; breakPointThis = 7; } if (g_debugCounter >= (debugEncoderSearchBinTargetLine + debugEncoderSearchBinWindow)) { exit(0); } g_debugCounter++; #endif } /** * \brief Encode equiprobable bin * * \param binValue bin value */ Void TEncBinCABACCounter::encodeBinEP( UInt /*binValue*/ ) { m_uiBinsCoded += m_binCountIncrement; m_fracBits += 32768; } /** * \brief Encode equiprobable bins * * \param binValues bin values * \param numBins number of bins */ Void TEncBinCABACCounter::encodeBinsEP( UInt /*binValues*/, Int numBins ) { m_uiBinsCoded += numBins & -m_binCountIncrement; m_fracBits += 32768 * numBins; } /** * \brief Encode terminating bin * * \param binValue bin value */ Void TEncBinCABACCounter::encodeBinTrm( UInt binValue ) { m_uiBinsCoded += m_binCountIncrement; m_fracBits += ContextModel::getEntropyBitsTrm( binValue ); } Void TEncBinCABACCounter::align() { m_fracBits = (m_fracBits + 32767) & (~32767); } //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncBinCoderCABACCounter.h000066400000000000000000000050731442026013100230700ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncBinCoderCABAC.h \brief binary entropy encoder of CABAC */ #ifndef __TENCBINCODERCABACCOUNTER__ #define __TENCBINCODERCABACCOUNTER__ #include "TEncBinCoderCABAC.h" #if FAST_BIT_EST //! \ingroup TLibEncoder //! \{ class TEncBinCABACCounter : public TEncBinCABAC { public: TEncBinCABACCounter (); virtual ~TEncBinCABACCounter(); Void finish (); UInt getNumWrittenBits (); Void encodeBin ( UInt binValue, ContextModel& rcCtxModel ); Void encodeBinEP ( UInt binValue ); Void encodeBinsEP ( UInt binValues, Int numBins ); Void encodeBinTrm ( UInt binValue ); Void align (); private: }; //! \} #endif #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncCavlc.cpp000066400000000000000000001773021442026013100207210ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncCavlc.cpp \brief CAVLC encoder class */ #include "../TLibCommon/CommonDef.h" #include "TEncCavlc.h" #include "SEIwrite.h" //! \ingroup TLibEncoder //! \{ #if ENC_DEC_TRACE #if MCTS_EXTRACTION Void xTraceVPSHeaderEnc() #else Void xTraceVPSHeader() #endif { fprintf( g_hTrace, "=========== Video Parameter Set ===========\n" ); } #if MCTS_EXTRACTION Void xTraceSPSHeaderEnc() #else Void xTraceSPSHeader() #endif { fprintf( g_hTrace, "=========== Sequence Parameter Set ===========\n" ); } #if MCTS_EXTRACTION Void xTracePPSHeaderEnc() #else Void xTracePPSHeader() #endif { fprintf( g_hTrace, "=========== Picture Parameter Set ===========\n"); } #if MCTS_EXTRACTION Void xTraceSliceHeaderEnc() #else Void xTraceSliceHeader() #endif { fprintf( g_hTrace, "=========== Slice ===========\n"); } #if MCTS_EXTRACTION Void xTraceAccessUnitDelimiterEnc() #else Void xTraceAccessUnitDelimiter() #endif { fprintf( g_hTrace, "=========== Access Unit Delimiter ===========\n"); } #endif Void AUDWriter::codeAUD(TComBitIf& bs, const Int pictureType) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceAccessUnitDelimiterEnc(); #else xTraceAccessUnitDelimiter(); #endif #endif assert (pictureType < 3); setBitstream(&bs); WRITE_CODE(pictureType, 3, "pic_type"); xWriteRbspTrailingBits(); } // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TEncCavlc::TEncCavlc() { m_pcBitIf = NULL; } TEncCavlc::~TEncCavlc() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TEncCavlc::resetEntropy(const TComSlice* /*pSlice*/) { } Void TEncCavlc::codeShortTermRefPicSet( const TComReferencePictureSet* rps, Bool calledFromSliceHeader, Int idx) { #if PRINT_RPS_INFO Int lastBits = getNumberOfWrittenBits(); #endif if (idx > 0) { WRITE_FLAG( rps->getInterRPSPrediction(), "inter_ref_pic_set_prediction_flag" ); // inter_RPS_prediction_flag } if (rps->getInterRPSPrediction()) { Int deltaRPS = rps->getDeltaRPS(); if(calledFromSliceHeader) { WRITE_UVLC( rps->getDeltaRIdxMinus1(), "delta_idx_minus1" ); // delta index of the Reference Picture Set used for prediction minus 1 } WRITE_CODE( (deltaRPS >=0 ? 0: 1), 1, "delta_rps_sign" ); //delta_rps_sign WRITE_UVLC( abs(deltaRPS) - 1, "abs_delta_rps_minus1"); // absolute delta RPS minus 1 for(Int j=0; j < rps->getNumRefIdc(); j++) { Int refIdc = rps->getRefIdc(j); WRITE_CODE( (refIdc==1? 1: 0), 1, "used_by_curr_pic_flag" ); //first bit is "1" if Idc is 1 if (refIdc != 1) { WRITE_CODE( refIdc>>1, 1, "use_delta_flag" ); //second bit is "1" if Idc is 2, "0" otherwise. } } } else { WRITE_UVLC( rps->getNumberOfNegativePictures(), "num_negative_pics" ); WRITE_UVLC( rps->getNumberOfPositivePictures(), "num_positive_pics" ); Int prev = 0; for(Int j=0 ; j < rps->getNumberOfNegativePictures(); j++) { WRITE_UVLC( prev-rps->getDeltaPOC(j)-1, "delta_poc_s0_minus1" ); prev = rps->getDeltaPOC(j); WRITE_FLAG( rps->getUsed(j), "used_by_curr_pic_s0_flag"); } prev = 0; for(Int j=rps->getNumberOfNegativePictures(); j < rps->getNumberOfNegativePictures()+rps->getNumberOfPositivePictures(); j++) { WRITE_UVLC( rps->getDeltaPOC(j)-prev-1, "delta_poc_s1_minus1" ); prev = rps->getDeltaPOC(j); WRITE_FLAG( rps->getUsed(j), "used_by_curr_pic_s1_flag" ); } } #if PRINT_RPS_INFO printf("irps=%d (%2d bits) ", rps->getInterRPSPrediction(), getNumberOfWrittenBits() - lastBits); rps->printDeltaPOC(); #endif } Void TEncCavlc::codePPS( const TComPPS* pcPPS ) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTracePPSHeaderEnc(); #else xTracePPSHeader(); #endif #endif WRITE_UVLC( pcPPS->getPPSId(), "pps_pic_parameter_set_id" ); WRITE_UVLC( pcPPS->getSPSId(), "pps_seq_parameter_set_id" ); WRITE_FLAG( pcPPS->getDependentSliceSegmentsEnabledFlag() ? 1 : 0, "dependent_slice_segments_enabled_flag" ); WRITE_FLAG( pcPPS->getOutputFlagPresentFlag() ? 1 : 0, "output_flag_present_flag" ); WRITE_CODE( pcPPS->getNumExtraSliceHeaderBits(), 3, "num_extra_slice_header_bits"); WRITE_FLAG( pcPPS->getSignDataHidingEnabledFlag(), "sign_data_hiding_enabled_flag" ); WRITE_FLAG( pcPPS->getCabacInitPresentFlag() ? 1 : 0, "cabac_init_present_flag" ); WRITE_UVLC( pcPPS->getNumRefIdxL0DefaultActive()-1, "num_ref_idx_l0_default_active_minus1"); WRITE_UVLC( pcPPS->getNumRefIdxL1DefaultActive()-1, "num_ref_idx_l1_default_active_minus1"); WRITE_SVLC( pcPPS->getPicInitQPMinus26(), "init_qp_minus26"); WRITE_FLAG( pcPPS->getConstrainedIntraPred() ? 1 : 0, "constrained_intra_pred_flag" ); WRITE_FLAG( pcPPS->getUseTransformSkip() ? 1 : 0, "transform_skip_enabled_flag" ); WRITE_FLAG( pcPPS->getUseDQP() ? 1 : 0, "cu_qp_delta_enabled_flag" ); if ( pcPPS->getUseDQP() ) { WRITE_UVLC( pcPPS->getMaxCuDQPDepth(), "diff_cu_qp_delta_depth" ); } WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cb), "pps_cb_qp_offset" ); WRITE_SVLC( pcPPS->getQpOffset(COMPONENT_Cr), "pps_cr_qp_offset" ); WRITE_FLAG( pcPPS->getSliceChromaQpFlag() ? 1 : 0, "pps_slice_chroma_qp_offsets_present_flag" ); WRITE_FLAG( pcPPS->getUseWP() ? 1 : 0, "weighted_pred_flag" ); // Use of Weighting Prediction (P_SLICE) WRITE_FLAG( pcPPS->getWPBiPred() ? 1 : 0, "weighted_bipred_flag" ); // Use of Weighting Bi-Prediction (B_SLICE) WRITE_FLAG( pcPPS->getTransquantBypassEnabledFlag() ? 1 : 0, "transquant_bypass_enabled_flag" ); WRITE_FLAG( pcPPS->getTilesEnabledFlag() ? 1 : 0, "tiles_enabled_flag" ); WRITE_FLAG( pcPPS->getEntropyCodingSyncEnabledFlag() ? 1 : 0, "entropy_coding_sync_enabled_flag" ); if( pcPPS->getTilesEnabledFlag() ) { WRITE_UVLC( pcPPS->getNumTileColumnsMinus1(), "num_tile_columns_minus1" ); WRITE_UVLC( pcPPS->getNumTileRowsMinus1(), "num_tile_rows_minus1" ); WRITE_FLAG( pcPPS->getTileUniformSpacingFlag(), "uniform_spacing_flag" ); if( !pcPPS->getTileUniformSpacingFlag() ) { for(UInt i=0; igetNumTileColumnsMinus1(); i++) { WRITE_UVLC( pcPPS->getTileColumnWidth(i)-1, "column_width_minus1" ); } for(UInt i=0; igetNumTileRowsMinus1(); i++) { WRITE_UVLC( pcPPS->getTileRowHeight(i)-1, "row_height_minus1" ); } } assert ((pcPPS->getNumTileColumnsMinus1() + pcPPS->getNumTileRowsMinus1()) != 0); WRITE_FLAG( pcPPS->getLoopFilterAcrossTilesEnabledFlag()?1 : 0, "loop_filter_across_tiles_enabled_flag"); } WRITE_FLAG( pcPPS->getLoopFilterAcrossSlicesEnabledFlag()?1 : 0, "pps_loop_filter_across_slices_enabled_flag"); WRITE_FLAG( pcPPS->getDeblockingFilterControlPresentFlag()?1 : 0, "deblocking_filter_control_present_flag"); if(pcPPS->getDeblockingFilterControlPresentFlag()) { WRITE_FLAG( pcPPS->getDeblockingFilterOverrideEnabledFlag() ? 1 : 0, "deblocking_filter_override_enabled_flag" ); WRITE_FLAG( pcPPS->getPPSDeblockingFilterDisabledFlag() ? 1 : 0, "pps_deblocking_filter_disabled_flag" ); if(!pcPPS->getPPSDeblockingFilterDisabledFlag()) { WRITE_SVLC( pcPPS->getDeblockingFilterBetaOffsetDiv2(), "pps_beta_offset_div2" ); WRITE_SVLC( pcPPS->getDeblockingFilterTcOffsetDiv2(), "pps_tc_offset_div2" ); } } WRITE_FLAG( pcPPS->getScalingListPresentFlag() ? 1 : 0, "pps_scaling_list_data_present_flag" ); if( pcPPS->getScalingListPresentFlag() ) { codeScalingList( pcPPS->getScalingList() ); } WRITE_FLAG( pcPPS->getListsModificationPresentFlag(), "lists_modification_present_flag"); WRITE_UVLC( pcPPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2"); WRITE_FLAG( pcPPS->getSliceHeaderExtensionPresentFlag() ? 1 : 0, "slice_segment_header_extension_present_flag"); Bool pps_extension_present_flag=false; Bool pps_extension_flags[NUM_PPS_EXTENSION_FLAGS]={false}; pps_extension_flags[PPS_EXT__REXT] = pcPPS->getPpsRangeExtension().settingsDifferFromDefaults(pcPPS->getUseTransformSkip()); // Other PPS extension flags checked here. for(Int i=0; igetPpsRangeExtension(); if (pcPPS->getUseTransformSkip()) { WRITE_UVLC( ppsRangeExtension.getLog2MaxTransformSkipBlockSize()-2, "log2_max_transform_skip_block_size_minus2"); } WRITE_FLAG((ppsRangeExtension.getCrossComponentPredictionEnabledFlag() ? 1 : 0), "cross_component_prediction_enabled_flag" ); WRITE_FLAG(UInt(ppsRangeExtension.getChromaQpOffsetListEnabledFlag()), "chroma_qp_offset_list_enabled_flag" ); if (ppsRangeExtension.getChromaQpOffsetListEnabledFlag()) { WRITE_UVLC(ppsRangeExtension.getDiffCuChromaQpOffsetDepth(), "diff_cu_chroma_qp_offset_depth"); WRITE_UVLC(ppsRangeExtension.getChromaQpOffsetListLen() - 1, "chroma_qp_offset_list_len_minus1"); /* skip zero index */ for (Int cuChromaQpOffsetIdx = 0; cuChromaQpOffsetIdx < ppsRangeExtension.getChromaQpOffsetListLen(); cuChromaQpOffsetIdx++) { WRITE_SVLC(ppsRangeExtension.getChromaQpOffsetListEntry(cuChromaQpOffsetIdx+1).u.comp.CbOffset, "cb_qp_offset_list[i]"); WRITE_SVLC(ppsRangeExtension.getChromaQpOffsetListEntry(cuChromaQpOffsetIdx+1).u.comp.CrOffset, "cr_qp_offset_list[i]"); } } WRITE_UVLC( ppsRangeExtension.getLog2SaoOffsetScale(CHANNEL_TYPE_LUMA), "log2_sao_offset_scale_luma" ); WRITE_UVLC( ppsRangeExtension.getLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA), "log2_sao_offset_scale_chroma" ); } break; default: assert(pps_extension_flags[i]==false); // Should never get here with an active PPS extension flag. break; } // switch } // if flag present } // loop over PPS flags } // pps_extension_present_flag is non-zero xWriteRbspTrailingBits(); } Void TEncCavlc::codeVUI( const TComVUI *pcVUI, const TComSPS* pcSPS ) { #if ENC_DEC_TRACE fprintf( g_hTrace, "----------- vui_parameters -----------\n"); #endif WRITE_FLAG(pcVUI->getAspectRatioInfoPresentFlag(), "aspect_ratio_info_present_flag"); if (pcVUI->getAspectRatioInfoPresentFlag()) { WRITE_CODE(pcVUI->getAspectRatioIdc(), 8, "aspect_ratio_idc" ); if (pcVUI->getAspectRatioIdc() == 255) { WRITE_CODE(pcVUI->getSarWidth(), 16, "sar_width"); WRITE_CODE(pcVUI->getSarHeight(), 16, "sar_height"); } } WRITE_FLAG(pcVUI->getOverscanInfoPresentFlag(), "overscan_info_present_flag"); if (pcVUI->getOverscanInfoPresentFlag()) { WRITE_FLAG(pcVUI->getOverscanAppropriateFlag(), "overscan_appropriate_flag"); } WRITE_FLAG(pcVUI->getVideoSignalTypePresentFlag(), "video_signal_type_present_flag"); if (pcVUI->getVideoSignalTypePresentFlag()) { WRITE_CODE(pcVUI->getVideoFormat(), 3, "video_format"); WRITE_FLAG(pcVUI->getVideoFullRangeFlag(), "video_full_range_flag"); WRITE_FLAG(pcVUI->getColourDescriptionPresentFlag(), "colour_description_present_flag"); if (pcVUI->getColourDescriptionPresentFlag()) { WRITE_CODE(pcVUI->getColourPrimaries(), 8, "colour_primaries"); WRITE_CODE(pcVUI->getTransferCharacteristics(), 8, "transfer_characteristics"); WRITE_CODE(pcVUI->getMatrixCoefficients(), 8, "matrix_coeffs"); } } WRITE_FLAG(pcVUI->getChromaLocInfoPresentFlag(), "chroma_loc_info_present_flag"); if (pcVUI->getChromaLocInfoPresentFlag()) { WRITE_UVLC(pcVUI->getChromaSampleLocTypeTopField(), "chroma_sample_loc_type_top_field"); WRITE_UVLC(pcVUI->getChromaSampleLocTypeBottomField(), "chroma_sample_loc_type_bottom_field"); } WRITE_FLAG(pcVUI->getNeutralChromaIndicationFlag(), "neutral_chroma_indication_flag"); WRITE_FLAG(pcVUI->getFieldSeqFlag(), "field_seq_flag"); WRITE_FLAG(pcVUI->getFrameFieldInfoPresentFlag(), "frame_field_info_present_flag"); Window defaultDisplayWindow = pcVUI->getDefaultDisplayWindow(); WRITE_FLAG(defaultDisplayWindow.getWindowEnabledFlag(), "default_display_window_flag"); if( defaultDisplayWindow.getWindowEnabledFlag() ) { WRITE_UVLC(defaultDisplayWindow.getWindowLeftOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc()), "def_disp_win_left_offset"); WRITE_UVLC(defaultDisplayWindow.getWindowRightOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc()), "def_disp_win_right_offset"); WRITE_UVLC(defaultDisplayWindow.getWindowTopOffset() / TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc()), "def_disp_win_top_offset"); WRITE_UVLC(defaultDisplayWindow.getWindowBottomOffset()/ TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc()), "def_disp_win_bottom_offset"); } const TimingInfo *timingInfo = pcVUI->getTimingInfo(); WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(), "vui_timing_info_present_flag"); if(timingInfo->getTimingInfoPresentFlag()) { WRITE_CODE(timingInfo->getNumUnitsInTick(), 32, "vui_num_units_in_tick"); WRITE_CODE(timingInfo->getTimeScale(), 32, "vui_time_scale"); WRITE_FLAG(timingInfo->getPocProportionalToTimingFlag(), "vui_poc_proportional_to_timing_flag"); if(timingInfo->getPocProportionalToTimingFlag()) { WRITE_UVLC(timingInfo->getNumTicksPocDiffOneMinus1(), "vui_num_ticks_poc_diff_one_minus1"); } WRITE_FLAG(pcVUI->getHrdParametersPresentFlag(), "vui_hrd_parameters_present_flag"); if( pcVUI->getHrdParametersPresentFlag() ) { codeHrdParameters(pcVUI->getHrdParameters(), 1, pcSPS->getMaxTLayers() - 1 ); } } WRITE_FLAG(pcVUI->getBitstreamRestrictionFlag(), "bitstream_restriction_flag"); if (pcVUI->getBitstreamRestrictionFlag()) { WRITE_FLAG(pcVUI->getTilesFixedStructureFlag(), "tiles_fixed_structure_flag"); WRITE_FLAG(pcVUI->getMotionVectorsOverPicBoundariesFlag(), "motion_vectors_over_pic_boundaries_flag"); WRITE_FLAG(pcVUI->getRestrictedRefPicListsFlag(), "restricted_ref_pic_lists_flag"); WRITE_UVLC(pcVUI->getMinSpatialSegmentationIdc(), "min_spatial_segmentation_idc"); WRITE_UVLC(pcVUI->getMaxBytesPerPicDenom(), "max_bytes_per_pic_denom"); WRITE_UVLC(pcVUI->getMaxBitsPerMinCuDenom(), "max_bits_per_min_cu_denom"); WRITE_UVLC(pcVUI->getLog2MaxMvLengthHorizontal(), "log2_max_mv_length_horizontal"); WRITE_UVLC(pcVUI->getLog2MaxMvLengthVertical(), "log2_max_mv_length_vertical"); } } Void TEncCavlc::codeHrdParameters( const TComHRD *hrd, Bool commonInfPresentFlag, UInt maxNumSubLayersMinus1 ) { if( commonInfPresentFlag ) { WRITE_FLAG( hrd->getNalHrdParametersPresentFlag() ? 1 : 0 , "nal_hrd_parameters_present_flag" ); WRITE_FLAG( hrd->getVclHrdParametersPresentFlag() ? 1 : 0 , "vcl_hrd_parameters_present_flag" ); if( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) { WRITE_FLAG( hrd->getSubPicCpbParamsPresentFlag() ? 1 : 0, "sub_pic_hrd_params_present_flag" ); if( hrd->getSubPicCpbParamsPresentFlag() ) { WRITE_CODE( hrd->getTickDivisorMinus2(), 8, "tick_divisor_minus2" ); WRITE_CODE( hrd->getDuCpbRemovalDelayLengthMinus1(), 5, "du_cpb_removal_delay_increment_length_minus1" ); WRITE_FLAG( hrd->getSubPicCpbParamsInPicTimingSEIFlag() ? 1 : 0, "sub_pic_cpb_params_in_pic_timing_sei_flag" ); WRITE_CODE( hrd->getDpbOutputDelayDuLengthMinus1(), 5, "dpb_output_delay_du_length_minus1" ); } WRITE_CODE( hrd->getBitRateScale(), 4, "bit_rate_scale" ); WRITE_CODE( hrd->getCpbSizeScale(), 4, "cpb_size_scale" ); if( hrd->getSubPicCpbParamsPresentFlag() ) { WRITE_CODE( hrd->getDuCpbSizeScale(), 4, "du_cpb_size_scale" ); } WRITE_CODE( hrd->getInitialCpbRemovalDelayLengthMinus1(), 5, "initial_cpb_removal_delay_length_minus1" ); WRITE_CODE( hrd->getCpbRemovalDelayLengthMinus1(), 5, "au_cpb_removal_delay_length_minus1" ); WRITE_CODE( hrd->getDpbOutputDelayLengthMinus1(), 5, "dpb_output_delay_length_minus1" ); } } Int i, j, nalOrVcl; for( i = 0; i <= maxNumSubLayersMinus1; i ++ ) { WRITE_FLAG( hrd->getFixedPicRateFlag( i ) ? 1 : 0, "fixed_pic_rate_general_flag"); Bool fixedPixRateWithinCvsFlag = true; if( !hrd->getFixedPicRateFlag( i ) ) { fixedPixRateWithinCvsFlag = hrd->getFixedPicRateWithinCvsFlag( i ); WRITE_FLAG( hrd->getFixedPicRateWithinCvsFlag( i ) ? 1 : 0, "fixed_pic_rate_within_cvs_flag"); } if( fixedPixRateWithinCvsFlag ) { WRITE_UVLC( hrd->getPicDurationInTcMinus1( i ), "elemental_duration_in_tc_minus1"); } else { WRITE_FLAG( hrd->getLowDelayHrdFlag( i ) ? 1 : 0, "low_delay_hrd_flag"); } if (!hrd->getLowDelayHrdFlag( i )) { WRITE_UVLC( hrd->getCpbCntMinus1( i ), "cpb_cnt_minus1"); } for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ ) { if( ( ( nalOrVcl == 0 ) && ( hrd->getNalHrdParametersPresentFlag() ) ) || ( ( nalOrVcl == 1 ) && ( hrd->getVclHrdParametersPresentFlag() ) ) ) { for( j = 0; j <= ( hrd->getCpbCntMinus1( i ) ); j ++ ) { WRITE_UVLC( hrd->getBitRateValueMinus1( i, j, nalOrVcl ), "bit_rate_value_minus1"); WRITE_UVLC( hrd->getCpbSizeValueMinus1( i, j, nalOrVcl ), "cpb_size_value_minus1"); if( hrd->getSubPicCpbParamsPresentFlag() ) { WRITE_UVLC( hrd->getDuCpbSizeValueMinus1( i, j, nalOrVcl ), "cpb_size_du_value_minus1"); WRITE_UVLC( hrd->getDuBitRateValueMinus1( i, j, nalOrVcl ), "bit_rate_du_value_minus1"); } WRITE_FLAG( hrd->getCbrFlag( i, j, nalOrVcl ) ? 1 : 0, "cbr_flag"); } } } } } Void TEncCavlc::codeSPS( const TComSPS* pcSPS ) { const ChromaFormat format = pcSPS->getChromaFormatIdc(); const Bool chromaEnabled = isChromaEnabled(format); #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceSPSHeaderEnc(); #else xTraceSPSHeader(); #endif #endif WRITE_CODE( pcSPS->getVPSId (), 4, "sps_video_parameter_set_id" ); WRITE_CODE( pcSPS->getMaxTLayers() - 1, 3, "sps_max_sub_layers_minus1" ); WRITE_FLAG( pcSPS->getTemporalIdNestingFlag() ? 1 : 0, "sps_temporal_id_nesting_flag" ); codePTL(pcSPS->getPTL(), 1, pcSPS->getMaxTLayers() - 1); WRITE_UVLC( pcSPS->getSPSId (), "sps_seq_parameter_set_id" ); WRITE_UVLC( Int(pcSPS->getChromaFormatIdc ()), "chroma_format_idc" ); if( format == CHROMA_444 ) { WRITE_FLAG( 0, "separate_colour_plane_flag"); } WRITE_UVLC( pcSPS->getPicWidthInLumaSamples (), "pic_width_in_luma_samples" ); WRITE_UVLC( pcSPS->getPicHeightInLumaSamples(), "pic_height_in_luma_samples" ); Window conf = pcSPS->getConformanceWindow(); WRITE_FLAG( conf.getWindowEnabledFlag(), "conformance_window_flag" ); if (conf.getWindowEnabledFlag()) { WRITE_UVLC( conf.getWindowLeftOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_left_offset" ); WRITE_UVLC( conf.getWindowRightOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_right_offset" ); WRITE_UVLC( conf.getWindowTopOffset() / TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_top_offset" ); WRITE_UVLC( conf.getWindowBottomOffset() / TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_bottom_offset" ); } WRITE_UVLC( pcSPS->getBitDepth(CHANNEL_TYPE_LUMA) - 8, "bit_depth_luma_minus8" ); WRITE_UVLC( chromaEnabled ? (pcSPS->getBitDepth(CHANNEL_TYPE_CHROMA) - 8):0, "bit_depth_chroma_minus8" ); WRITE_UVLC( pcSPS->getBitsForPOC()-4, "log2_max_pic_order_cnt_lsb_minus4" ); const Bool subLayerOrderingInfoPresentFlag = 1; WRITE_FLAG(subLayerOrderingInfoPresentFlag, "sps_sub_layer_ordering_info_present_flag"); for(UInt i=0; i <= pcSPS->getMaxTLayers()-1; i++) { WRITE_UVLC( pcSPS->getMaxDecPicBuffering(i) - 1, "sps_max_dec_pic_buffering_minus1[i]" ); WRITE_UVLC( pcSPS->getNumReorderPics(i), "sps_max_num_reorder_pics[i]" ); WRITE_UVLC( pcSPS->getMaxLatencyIncreasePlus1(i), "sps_max_latency_increase_plus1[i]" ); if (!subLayerOrderingInfoPresentFlag) { break; } } assert( pcSPS->getMaxCUWidth() == pcSPS->getMaxCUHeight() ); WRITE_UVLC( pcSPS->getLog2MinCodingBlockSize() - 3, "log2_min_luma_coding_block_size_minus3" ); WRITE_UVLC( pcSPS->getLog2DiffMaxMinCodingBlockSize(), "log2_diff_max_min_luma_coding_block_size" ); WRITE_UVLC( pcSPS->getQuadtreeTULog2MinSize() - 2, "log2_min_luma_transform_block_size_minus2" ); WRITE_UVLC( pcSPS->getQuadtreeTULog2MaxSize() - pcSPS->getQuadtreeTULog2MinSize(), "log2_diff_max_min_luma_transform_block_size" ); WRITE_UVLC( pcSPS->getQuadtreeTUMaxDepthInter() - 1, "max_transform_hierarchy_depth_inter" ); WRITE_UVLC( pcSPS->getQuadtreeTUMaxDepthIntra() - 1, "max_transform_hierarchy_depth_intra" ); WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0, "scaling_list_enabled_flag" ); if(pcSPS->getScalingListFlag()) { WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0, "sps_scaling_list_data_present_flag" ); if(pcSPS->getScalingListPresentFlag()) { codeScalingList( pcSPS->getScalingList() ); } } WRITE_FLAG( pcSPS->getUseAMP() ? 1 : 0, "amp_enabled_flag" ); WRITE_FLAG( pcSPS->getUseSAO() ? 1 : 0, "sample_adaptive_offset_enabled_flag"); WRITE_FLAG( pcSPS->getUsePCM() ? 1 : 0, "pcm_enabled_flag"); if( pcSPS->getUsePCM() ) { WRITE_CODE( pcSPS->getPCMBitDepth(CHANNEL_TYPE_LUMA) - 1, 4, "pcm_sample_bit_depth_luma_minus1" ); WRITE_CODE( chromaEnabled ? (pcSPS->getPCMBitDepth(CHANNEL_TYPE_CHROMA) - 1) : 0, 4, "pcm_sample_bit_depth_chroma_minus1" ); WRITE_UVLC( pcSPS->getPCMLog2MinSize() - 3, "log2_min_pcm_luma_coding_block_size_minus3" ); WRITE_UVLC( pcSPS->getPCMLog2MaxSize() - pcSPS->getPCMLog2MinSize(), "log2_diff_max_min_pcm_luma_coding_block_size" ); WRITE_FLAG( pcSPS->getPCMFilterDisableFlag()?1 : 0, "pcm_loop_filter_disable_flag"); } assert( pcSPS->getMaxTLayers() > 0 ); const TComRPSList* rpsList = pcSPS->getRPSList(); WRITE_UVLC(rpsList->getNumberOfReferencePictureSets(), "num_short_term_ref_pic_sets" ); for(Int i=0; i < rpsList->getNumberOfReferencePictureSets(); i++) { const TComReferencePictureSet*rps = rpsList->getReferencePictureSet(i); codeShortTermRefPicSet( rps,false, i); } WRITE_FLAG( pcSPS->getLongTermRefsPresent() ? 1 : 0, "long_term_ref_pics_present_flag" ); if (pcSPS->getLongTermRefsPresent()) { WRITE_UVLC(pcSPS->getNumLongTermRefPicSPS(), "num_long_term_ref_pics_sps" ); for (UInt k = 0; k < pcSPS->getNumLongTermRefPicSPS(); k++) { WRITE_CODE( pcSPS->getLtRefPicPocLsbSps(k), pcSPS->getBitsForPOC(), "lt_ref_pic_poc_lsb_sps"); WRITE_FLAG( pcSPS->getUsedByCurrPicLtSPSFlag(k), "used_by_curr_pic_lt_sps_flag[i]"); } } WRITE_FLAG( pcSPS->getSPSTemporalMVPEnabledFlag() ? 1 : 0, "sps_temporal_mvp_enabled_flag" ); WRITE_FLAG( pcSPS->getUseStrongIntraSmoothing(), "strong_intra_smoothing_enable_flag" ); WRITE_FLAG( pcSPS->getVuiParametersPresentFlag(), "vui_parameters_present_flag" ); if (pcSPS->getVuiParametersPresentFlag()) { codeVUI(pcSPS->getVuiParameters(), pcSPS); } Bool sps_extension_present_flag=false; Bool sps_extension_flags[NUM_SPS_EXTENSION_FLAGS]={false}; sps_extension_flags[SPS_EXT__REXT] = pcSPS->getSpsRangeExtension().settingsDifferFromDefaults(); // Other SPS extension flags checked here. for(Int i=0; igetSpsRangeExtension(); WRITE_FLAG( (spsRangeExtension.getTransformSkipRotationEnabledFlag() ? 1 : 0), "transform_skip_rotation_enabled_flag"); WRITE_FLAG( (spsRangeExtension.getTransformSkipContextEnabledFlag() ? 1 : 0), "transform_skip_context_enabled_flag"); WRITE_FLAG( (spsRangeExtension.getRdpcmEnabledFlag(RDPCM_SIGNAL_IMPLICIT) ? 1 : 0), "implicit_rdpcm_enabled_flag" ); WRITE_FLAG( (spsRangeExtension.getRdpcmEnabledFlag(RDPCM_SIGNAL_EXPLICIT) ? 1 : 0), "explicit_rdpcm_enabled_flag" ); WRITE_FLAG( (spsRangeExtension.getExtendedPrecisionProcessingFlag() ? 1 : 0), "extended_precision_processing_flag" ); WRITE_FLAG( (spsRangeExtension.getIntraSmoothingDisabledFlag() ? 1 : 0), "intra_smoothing_disabled_flag" ); WRITE_FLAG( (spsRangeExtension.getHighPrecisionOffsetsEnabledFlag() ? 1 : 0), "high_precision_offsets_enabled_flag" ); WRITE_FLAG( (spsRangeExtension.getPersistentRiceAdaptationEnabledFlag() ? 1 : 0), "persistent_rice_adaptation_enabled_flag" ); WRITE_FLAG( (spsRangeExtension.getCabacBypassAlignmentEnabledFlag() ? 1 : 0), "cabac_bypass_alignment_enabled_flag" ); break; } default: assert(sps_extension_flags[i]==false); // Should never get here with an active SPS extension flag. break; } } } } xWriteRbspTrailingBits(); } Void TEncCavlc::codeVPS( const TComVPS* pcVPS ) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceVPSHeaderEnc(); #else xTraceVPSHeader(); #endif #endif WRITE_CODE( pcVPS->getVPSId(), 4, "vps_video_parameter_set_id" ); WRITE_FLAG( 1, "vps_base_layer_internal_flag" ); WRITE_FLAG( 1, "vps_base_layer_available_flag" ); WRITE_CODE( 0, 6, "vps_max_layers_minus1" ); WRITE_CODE( pcVPS->getMaxTLayers() - 1, 3, "vps_max_sub_layers_minus1" ); WRITE_FLAG( pcVPS->getTemporalNestingFlag(), "vps_temporal_id_nesting_flag" ); assert (pcVPS->getMaxTLayers()>1||pcVPS->getTemporalNestingFlag()); WRITE_CODE( 0xffff, 16, "vps_reserved_0xffff_16bits" ); codePTL( pcVPS->getPTL(), true, pcVPS->getMaxTLayers() - 1 ); const Bool subLayerOrderingInfoPresentFlag = 1; WRITE_FLAG(subLayerOrderingInfoPresentFlag, "vps_sub_layer_ordering_info_present_flag"); for(UInt i=0; i <= pcVPS->getMaxTLayers()-1; i++) { WRITE_UVLC( pcVPS->getMaxDecPicBuffering(i) - 1, "vps_max_dec_pic_buffering_minus1[i]" ); WRITE_UVLC( pcVPS->getNumReorderPics(i), "vps_max_num_reorder_pics[i]" ); WRITE_UVLC( pcVPS->getMaxLatencyIncrease(i), "vps_max_latency_increase_plus1[i]" ); if (!subLayerOrderingInfoPresentFlag) { break; } } assert( pcVPS->getNumHrdParameters() <= MAX_VPS_NUM_HRD_PARAMETERS ); assert( pcVPS->getMaxNuhReservedZeroLayerId() < MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 ); WRITE_CODE( pcVPS->getMaxNuhReservedZeroLayerId(), 6, "vps_max_layer_id" ); WRITE_UVLC( pcVPS->getMaxOpSets() - 1, "vps_num_layer_sets_minus1" ); for( UInt opsIdx = 1; opsIdx <= ( pcVPS->getMaxOpSets() - 1 ); opsIdx ++ ) { // Operation point set for( UInt i = 0; i <= pcVPS->getMaxNuhReservedZeroLayerId(); i ++ ) { // Only applicable for version 1 // pcVPS->setLayerIdIncludedFlag( true, opsIdx, i ); WRITE_FLAG( pcVPS->getLayerIdIncludedFlag( opsIdx, i ) ? 1 : 0, "layer_id_included_flag[opsIdx][i]" ); } } const TimingInfo *timingInfo = pcVPS->getTimingInfo(); WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(), "vps_timing_info_present_flag"); if(timingInfo->getTimingInfoPresentFlag()) { WRITE_CODE(timingInfo->getNumUnitsInTick(), 32, "vps_num_units_in_tick"); WRITE_CODE(timingInfo->getTimeScale(), 32, "vps_time_scale"); WRITE_FLAG(timingInfo->getPocProportionalToTimingFlag(), "vps_poc_proportional_to_timing_flag"); if(timingInfo->getPocProportionalToTimingFlag()) { WRITE_UVLC(timingInfo->getNumTicksPocDiffOneMinus1(), "vps_num_ticks_poc_diff_one_minus1"); } WRITE_UVLC( pcVPS->getNumHrdParameters(), "vps_num_hrd_parameters" ); if( pcVPS->getNumHrdParameters() > 0 ) { for( UInt i = 0; i < pcVPS->getNumHrdParameters(); i ++ ) { // Only applicable for version 1 WRITE_UVLC( pcVPS->getHrdOpSetIdx( i ), "hrd_layer_set_idx" ); if( i > 0 ) { WRITE_FLAG( pcVPS->getCprmsPresentFlag( i ) ? 1 : 0, "cprms_present_flag[i]" ); } codeHrdParameters(pcVPS->getHrdParameters(i), pcVPS->getCprmsPresentFlag( i ), pcVPS->getMaxTLayers() - 1); } } } WRITE_FLAG( 0, "vps_extension_flag" ); //future extensions here.. xWriteRbspTrailingBits(); } Void TEncCavlc::codeSliceHeader ( TComSlice* pcSlice ) { #if ENC_DEC_TRACE #if MCTS_EXTRACTION xTraceSliceHeaderEnc(); #else xTraceSliceHeader(); #endif #endif const ChromaFormat format = pcSlice->getSPS()->getChromaFormatIdc(); const UInt numberValidComponents = getNumberValidComponents(format); const Bool chromaEnabled = isChromaEnabled(format); //calculate number of bits required for slice address Int maxSliceSegmentAddress = pcSlice->getPic()->getNumberOfCtusInFrame(); Int bitsSliceSegmentAddress = 0; while(maxSliceSegmentAddress>(1<getSliceSegmentCurStartCtuTsAddr(); //write slice address const Int sliceSegmentRsAddress = pcSlice->getPic()->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddress); WRITE_FLAG( sliceSegmentRsAddress==0, "first_slice_segment_in_pic_flag" ); if ( pcSlice->getRapPicFlag() ) { WRITE_FLAG( pcSlice->getNoOutputPriorPicsFlag() ? 1 : 0, "no_output_of_prior_pics_flag" ); } WRITE_UVLC( pcSlice->getPPS()->getPPSId(), "slice_pic_parameter_set_id" ); if ( pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag() && (sliceSegmentRsAddress!=0) ) { WRITE_FLAG( pcSlice->getDependentSliceSegmentFlag() ? 1 : 0, "dependent_slice_segment_flag" ); } if(sliceSegmentRsAddress>0) { WRITE_CODE( sliceSegmentRsAddress, bitsSliceSegmentAddress, "slice_segment_address" ); } if ( !pcSlice->getDependentSliceSegmentFlag() ) { for (Int i = 0; i < pcSlice->getPPS()->getNumExtraSliceHeaderBits(); i++) { WRITE_FLAG(0, "slice_reserved_flag[]"); } WRITE_UVLC( pcSlice->getSliceType(), "slice_type" ); if( pcSlice->getPPS()->getOutputFlagPresentFlag() ) { WRITE_FLAG( pcSlice->getPicOutputFlag() ? 1 : 0, "pic_output_flag" ); } if( !pcSlice->getIdrPicFlag() ) { Int picOrderCntLSB = (pcSlice->getPOC()-pcSlice->getLastIDR()+(1<getSPS()->getBitsForPOC())) & ((1<getSPS()->getBitsForPOC())-1); WRITE_CODE( picOrderCntLSB, pcSlice->getSPS()->getBitsForPOC(), "slice_pic_order_cnt_lsb"); const TComReferencePictureSet* rps = pcSlice->getRPS(); // check for bitstream restriction stating that: // If the current picture is a BLA or CRA picture, the value of NumPocTotalCurr shall be equal to 0. // Ideally this process should not be repeated for each slice in a picture if (pcSlice->isIRAP()) { for (Int picIdx = 0; picIdx < rps->getNumberOfPictures(); picIdx++) { assert (!rps->getUsed(picIdx)); } } if(pcSlice->getRPSidx() < 0) { WRITE_FLAG( 0, "short_term_ref_pic_set_sps_flag"); codeShortTermRefPicSet( rps, true, pcSlice->getSPS()->getRPSList()->getNumberOfReferencePictureSets()); } else { WRITE_FLAG( 1, "short_term_ref_pic_set_sps_flag"); Int numBits = 0; while ((1 << numBits) < pcSlice->getSPS()->getRPSList()->getNumberOfReferencePictureSets()) { numBits++; } if (numBits > 0) { WRITE_CODE( pcSlice->getRPSidx(), numBits, "short_term_ref_pic_set_idx" ); } } if(pcSlice->getSPS()->getLongTermRefsPresent()) { Int numLtrpInSH = rps->getNumberOfLongtermPictures(); Int ltrpInSPS[MAX_NUM_REF_PICS]; Int numLtrpInSPS = 0; UInt ltrpIndex; Int counter = 0; // WARNING: The following code only works only if a matching long-term RPS is // found in the SPS for ALL long-term pictures // The problem is that the SPS coded long-term pictures are moved to the // beginning of the list which causes a mismatch when no reference picture // list reordering is used // NB: Long-term coding is currently not supported in general by the HM encoder for(Int k = rps->getNumberOfPictures()-1; k > rps->getNumberOfPictures()-rps->getNumberOfLongtermPictures()-1; k--) { if (findMatchingLTRP(pcSlice, <rpIndex, rps->getPOC(k), rps->getUsed(k))) { ltrpInSPS[numLtrpInSPS] = ltrpIndex; numLtrpInSPS++; } else { counter++; } } numLtrpInSH -= numLtrpInSPS; // check that either all long-term pictures are coded in SPS or in slice header (no mixing) assert (numLtrpInSH==0 || numLtrpInSPS==0); Int bitsForLtrpInSPS = 0; while (pcSlice->getSPS()->getNumLongTermRefPicSPS() > (1 << bitsForLtrpInSPS)) { bitsForLtrpInSPS++; } if (pcSlice->getSPS()->getNumLongTermRefPicSPS() > 0) { WRITE_UVLC( numLtrpInSPS, "num_long_term_sps"); } WRITE_UVLC( numLtrpInSH, "num_long_term_pics"); // Note that the LSBs of the LT ref. pic. POCs must be sorted before. // Not sorted here because LT ref indices will be used in setRefPicList() Int prevDeltaMSB = 0, prevLSB = 0; Int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures(); counter = 0; // Warning: If some pictures are moved to ltrpInSPS, i is referring to a wrong index // (mapping would be required) for(Int i=rps->getNumberOfPictures()-1 ; i > offset-1; i--, counter++) { if (counter < numLtrpInSPS) { if (bitsForLtrpInSPS > 0) { WRITE_CODE( ltrpInSPS[counter], bitsForLtrpInSPS, "lt_idx_sps[i]"); } } else { WRITE_CODE( rps->getPocLSBLT(i), pcSlice->getSPS()->getBitsForPOC(), "poc_lsb_lt"); WRITE_FLAG( rps->getUsed(i), "used_by_curr_pic_lt_flag"); } WRITE_FLAG( rps->getDeltaPocMSBPresentFlag(i), "delta_poc_msb_present_flag"); if(rps->getDeltaPocMSBPresentFlag(i)) { Bool deltaFlag = false; // First LTRP from SPS || First LTRP from SH || curr LSB != prev LSB if( (i == rps->getNumberOfPictures()-1) || (i == rps->getNumberOfPictures()-1-numLtrpInSPS) || (rps->getPocLSBLT(i) != prevLSB) ) { deltaFlag = true; } if(deltaFlag) { WRITE_UVLC( rps->getDeltaPocMSBCycleLT(i), "delta_poc_msb_cycle_lt[i]" ); } else { Int differenceInDeltaMSB = rps->getDeltaPocMSBCycleLT(i) - prevDeltaMSB; assert(differenceInDeltaMSB >= 0); WRITE_UVLC( differenceInDeltaMSB, "delta_poc_msb_cycle_lt[i]" ); } prevLSB = rps->getPocLSBLT(i); prevDeltaMSB = rps->getDeltaPocMSBCycleLT(i); } } } if (pcSlice->getSPS()->getSPSTemporalMVPEnabledFlag()) { WRITE_FLAG( pcSlice->getEnableTMVPFlag() ? 1 : 0, "slice_temporal_mvp_enabled_flag" ); } } if(pcSlice->getSPS()->getUseSAO()) { WRITE_FLAG( pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA), "slice_sao_luma_flag" ); if (chromaEnabled) { WRITE_FLAG( pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA), "slice_sao_chroma_flag" ); } } //check if numrefidxes match the defaults. If not, override if (!pcSlice->isIntra()) { Bool overrideFlag = (pcSlice->getNumRefIdx( REF_PIC_LIST_0 )!=pcSlice->getPPS()->getNumRefIdxL0DefaultActive()||(pcSlice->isInterB()&&pcSlice->getNumRefIdx( REF_PIC_LIST_1 )!=pcSlice->getPPS()->getNumRefIdxL1DefaultActive())); WRITE_FLAG( overrideFlag ? 1 : 0, "num_ref_idx_active_override_flag"); if (overrideFlag) { WRITE_UVLC( pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) - 1, "num_ref_idx_l0_active_minus1" ); if (pcSlice->isInterB()) { WRITE_UVLC( pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) - 1, "num_ref_idx_l1_active_minus1" ); } else { pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); } } } else { pcSlice->setNumRefIdx(REF_PIC_LIST_0, 0); pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0); } if( pcSlice->getPPS()->getListsModificationPresentFlag() && pcSlice->getNumRpsCurrTempList() > 1) { TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification(); if(!pcSlice->isIntra()) { WRITE_FLAG(pcSlice->getRefPicListModification()->getRefPicListModificationFlagL0() ? 1 : 0, "ref_pic_list_modification_flag_l0" ); if (pcSlice->getRefPicListModification()->getRefPicListModificationFlagL0()) { Int numRpsCurrTempList0 = pcSlice->getNumRpsCurrTempList(); if (numRpsCurrTempList0 > 1) { Int length = 1; numRpsCurrTempList0 --; while ( numRpsCurrTempList0 >>= 1) { length ++; } for(Int i = 0; i < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); i++) { WRITE_CODE( refPicListModification->getRefPicSetIdxL0(i), length, "list_entry_l0"); } } } } if(pcSlice->isInterB()) { WRITE_FLAG(pcSlice->getRefPicListModification()->getRefPicListModificationFlagL1() ? 1 : 0, "ref_pic_list_modification_flag_l1" ); if (pcSlice->getRefPicListModification()->getRefPicListModificationFlagL1()) { Int numRpsCurrTempList1 = pcSlice->getNumRpsCurrTempList(); if ( numRpsCurrTempList1 > 1 ) { Int length = 1; numRpsCurrTempList1 --; while ( numRpsCurrTempList1 >>= 1) { length ++; } for(Int i = 0; i < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); i++) { WRITE_CODE( refPicListModification->getRefPicSetIdxL1(i), length, "list_entry_l1"); } } } } } if (pcSlice->isInterB()) { WRITE_FLAG( pcSlice->getMvdL1ZeroFlag() ? 1 : 0, "mvd_l1_zero_flag"); } if(!pcSlice->isIntra()) { if (!pcSlice->isIntra() && pcSlice->getPPS()->getCabacInitPresentFlag()) { #if MCTS_EXTRACTION Bool encCabacInitFlag = pcSlice->getCabacInitFlag(); #else SliceType sliceType = pcSlice->getSliceType(); SliceType encCABACTableIdx = pcSlice->getEncCABACTableIdx(); Bool encCabacInitFlag = (sliceType!=encCABACTableIdx && encCABACTableIdx!=I_SLICE) ? true : false; pcSlice->setCabacInitFlag( encCabacInitFlag ); #endif WRITE_FLAG( encCabacInitFlag?1:0, "cabac_init_flag" ); } } if ( pcSlice->getEnableTMVPFlag() ) { if ( pcSlice->getSliceType() == B_SLICE ) { WRITE_FLAG( pcSlice->getColFromL0Flag(), "collocated_from_l0_flag" ); } if ( pcSlice->getSliceType() != I_SLICE && ((pcSlice->getColFromL0Flag()==1 && pcSlice->getNumRefIdx(REF_PIC_LIST_0)>1)|| (pcSlice->getColFromL0Flag()==0 && pcSlice->getNumRefIdx(REF_PIC_LIST_1)>1))) { WRITE_UVLC( pcSlice->getColRefIdx(), "collocated_ref_idx" ); } } if ( (pcSlice->getPPS()->getUseWP() && pcSlice->getSliceType()==P_SLICE) || (pcSlice->getPPS()->getWPBiPred() && pcSlice->getSliceType()==B_SLICE) ) { xCodePredWeightTable( pcSlice ); } assert(pcSlice->getMaxNumMergeCand()<=MRG_MAX_NUM_CANDS); if (!pcSlice->isIntra()) { WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "five_minus_max_num_merge_cand"); } Int iCode = pcSlice->getSliceQp() - ( pcSlice->getPPS()->getPicInitQPMinus26() + 26 ); WRITE_SVLC( iCode, "slice_qp_delta" ); if (pcSlice->getPPS()->getSliceChromaQpFlag()) { if (numberValidComponents > COMPONENT_Cb) { WRITE_SVLC( pcSlice->getSliceChromaQpDelta(COMPONENT_Cb), "slice_cb_qp_offset" ); } if (numberValidComponents > COMPONENT_Cr) { WRITE_SVLC( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr), "slice_cr_qp_offset" ); } assert(numberValidComponents <= COMPONENT_Cr+1); } if (pcSlice->getPPS()->getPpsRangeExtension().getChromaQpOffsetListEnabledFlag()) { WRITE_FLAG(pcSlice->getUseChromaQpAdj(), "cu_chroma_qp_offset_enabled_flag"); } if (pcSlice->getPPS()->getDeblockingFilterControlPresentFlag()) { if (pcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() ) { WRITE_FLAG(pcSlice->getDeblockingFilterOverrideFlag(), "deblocking_filter_override_flag"); } if (pcSlice->getDeblockingFilterOverrideFlag()) { WRITE_FLAG(pcSlice->getDeblockingFilterDisable(), "slice_deblocking_filter_disabled_flag"); if(!pcSlice->getDeblockingFilterDisable()) { WRITE_SVLC (pcSlice->getDeblockingFilterBetaOffsetDiv2(), "slice_beta_offset_div2"); WRITE_SVLC (pcSlice->getDeblockingFilterTcOffsetDiv2(), "slice_tc_offset_div2"); } } } Bool isSAOEnabled = pcSlice->getSPS()->getUseSAO() && (pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_LUMA) || (chromaEnabled && pcSlice->getSaoEnabledFlag(CHANNEL_TYPE_CHROMA))); Bool isDBFEnabled = (!pcSlice->getDeblockingFilterDisable()); if(pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag() && ( isSAOEnabled || isDBFEnabled )) { WRITE_FLAG(pcSlice->getLFCrossSliceBoundaryFlag()?1:0, "slice_loop_filter_across_slices_enabled_flag"); } } if(pcSlice->getPPS()->getSliceHeaderExtensionPresentFlag()) { WRITE_UVLC(0,"slice_segment_header_extension_length"); } } Void TEncCavlc::codePTL( const TComPTL* pcPTL, Bool profilePresentFlag, Int maxNumSubLayersMinus1) { if(profilePresentFlag) { codeProfileTier(pcPTL->getGeneralPTL(), false); // general_... } WRITE_CODE( Int(pcPTL->getGeneralPTL()->getLevelIdc()), 8, "general_level_idc" ); for (Int i = 0; i < maxNumSubLayersMinus1; i++) { WRITE_FLAG( pcPTL->getSubLayerProfilePresentFlag(i), "sub_layer_profile_present_flag[i]" ); WRITE_FLAG( pcPTL->getSubLayerLevelPresentFlag(i), "sub_layer_level_present_flag[i]" ); } if (maxNumSubLayersMinus1 > 0) { for (Int i = maxNumSubLayersMinus1; i < 8; i++) { WRITE_CODE(0, 2, "reserved_zero_2bits"); } } for(Int i = 0; i < maxNumSubLayersMinus1; i++) { if( pcPTL->getSubLayerProfilePresentFlag(i) ) { codeProfileTier(pcPTL->getSubLayerPTL(i), true); // sub_layer_... } if( pcPTL->getSubLayerLevelPresentFlag(i) ) { WRITE_CODE( Int(pcPTL->getSubLayerPTL(i)->getLevelIdc()), 8, "sub_layer_level_idc[i]" ); } } } #if ENC_DEC_TRACE || RExt__DECODER_DEBUG_BIT_STATISTICS Void TEncCavlc::codeProfileTier( const ProfileTierLevel* ptl, const Bool bIsSubLayer ) #define PTL_TRACE_TEXT(txt) bIsSubLayer?("sub_layer_" txt) : ("general_" txt) #else Void TEncCavlc::codeProfileTier( const ProfileTierLevel* ptl, const Bool /*bIsSubLayer*/ ) #define PTL_TRACE_TEXT(txt) txt #endif { WRITE_CODE( ptl->getProfileSpace(), 2 , PTL_TRACE_TEXT("profile_space" )); WRITE_FLAG( ptl->getTierFlag()==Level::HIGH, PTL_TRACE_TEXT("tier_flag" )); WRITE_CODE( Int(ptl->getProfileIdc()), 5 , PTL_TRACE_TEXT("profile_idc" )); for(Int j = 0; j < 32; j++) { WRITE_FLAG( ptl->getProfileCompatibilityFlag(j), PTL_TRACE_TEXT("profile_compatibility_flag[][j]" )); } WRITE_FLAG(ptl->getProgressiveSourceFlag(), PTL_TRACE_TEXT("progressive_source_flag" )); WRITE_FLAG(ptl->getInterlacedSourceFlag(), PTL_TRACE_TEXT("interlaced_source_flag" )); WRITE_FLAG(ptl->getNonPackedConstraintFlag(), PTL_TRACE_TEXT("non_packed_constraint_flag" )); WRITE_FLAG(ptl->getFrameOnlyConstraintFlag(), PTL_TRACE_TEXT("frame_only_constraint_flag" )); if (ptl->getProfileIdc() == Profile::MAINREXT || ptl->getProfileIdc() == Profile::HIGHTHROUGHPUTREXT ) { const UInt bitDepthConstraint=ptl->getBitDepthConstraint(); WRITE_FLAG(bitDepthConstraint<=12, PTL_TRACE_TEXT("max_12bit_constraint_flag" )); WRITE_FLAG(bitDepthConstraint<=10, PTL_TRACE_TEXT("max_10bit_constraint_flag" )); WRITE_FLAG(bitDepthConstraint<= 8, PTL_TRACE_TEXT("max_8bit_constraint_flag" )); const ChromaFormat chromaFmtConstraint=ptl->getChromaFormatConstraint(); WRITE_FLAG(chromaFmtConstraint==CHROMA_422||chromaFmtConstraint==CHROMA_420||chromaFmtConstraint==CHROMA_400, PTL_TRACE_TEXT("max_422chroma_constraint_flag" )); WRITE_FLAG(chromaFmtConstraint==CHROMA_420||chromaFmtConstraint==CHROMA_400, PTL_TRACE_TEXT("max_420chroma_constraint_flag" )); WRITE_FLAG(chromaFmtConstraint==CHROMA_400, PTL_TRACE_TEXT("max_monochrome_constraint_flag")); WRITE_FLAG(ptl->getIntraConstraintFlag(), PTL_TRACE_TEXT("intra_constraint_flag" )); WRITE_FLAG(ptl->getOnePictureOnlyConstraintFlag(), PTL_TRACE_TEXT("one_picture_only_constraint_flag")); WRITE_FLAG(ptl->getLowerBitRateConstraintFlag(), PTL_TRACE_TEXT("lower_bit_rate_constraint_flag" )); WRITE_CODE(0 , 16, PTL_TRACE_TEXT("reserved_zero_34bits[0..15]" )); WRITE_CODE(0 , 16, PTL_TRACE_TEXT("reserved_zero_34bits[16..31]" )); WRITE_CODE(0 , 2, PTL_TRACE_TEXT("reserved_zero_34bits[32..33]" )); } else if (ptl->getProfileIdc() == Profile::MAIN10) { WRITE_CODE(0x00 , 7, PTL_TRACE_TEXT("reserved_zero_7bits" )); WRITE_FLAG(ptl->getOnePictureOnlyConstraintFlag(), PTL_TRACE_TEXT("one_picture_only_constraint_flag")); WRITE_CODE(0x0000 , 16, PTL_TRACE_TEXT("reserved_zero_35bits[0..15]" )); WRITE_CODE(0x0000 , 16, PTL_TRACE_TEXT("reserved_zero_35bits[16..31]" )); WRITE_CODE(0x0 , 3, PTL_TRACE_TEXT("reserved_zero_35bits[32..34]" )); } else { WRITE_CODE(0x0000 , 16, PTL_TRACE_TEXT("reserved_zero_43bits[0..15]" )); WRITE_CODE(0x0000 , 16, PTL_TRACE_TEXT("reserved_zero_43bits[16..31]" )); WRITE_CODE(0x000 , 11, PTL_TRACE_TEXT("reserved_zero_43bits[32..42]" )); } WRITE_FLAG(false, PTL_TRACE_TEXT("inbld_flag" )); #undef PTL_TRACE_TEXT } /** * Write tiles and wavefront substreams sizes for the slice header (entry points). * * \param pSlice TComSlice structure that contains the substream size information. */ Void TEncCavlc::codeTilesWPPEntryPoint( TComSlice* pSlice ) { if (!pSlice->getPPS()->getTilesEnabledFlag() && !pSlice->getPPS()->getEntropyCodingSyncEnabledFlag()) { return; } UInt maxOffset = 0; for(Int idx=0; idxgetNumberOfSubstreamSizes(); idx++) { UInt offset=pSlice->getSubstreamSize(idx); if ( offset > maxOffset ) { maxOffset = offset; } } // Determine number of bits "offsetLenMinus1+1" required for entry point information UInt offsetLenMinus1 = 0; while (maxOffset >= (1u << (offsetLenMinus1 + 1))) { offsetLenMinus1++; assert(offsetLenMinus1 + 1 < 32); } WRITE_UVLC(pSlice->getNumberOfSubstreamSizes(), "num_entry_point_offsets"); if (pSlice->getNumberOfSubstreamSizes()>0) { WRITE_UVLC(offsetLenMinus1, "offset_len_minus1"); for (UInt idx=0; idxgetNumberOfSubstreamSizes(); idx++) { WRITE_CODE(pSlice->getSubstreamSize(idx)-1, offsetLenMinus1+1, "entry_point_offset_minus1"); } } } Void TEncCavlc::codeTerminatingBit ( UInt /*uilsLast*/ ) { } Void TEncCavlc::codeSliceFinish () { } Void TEncCavlc::codeMVPIdx ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, RefPicList /*eRefList*/ ) { assert(0); } Void TEncCavlc::codePartSize( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TEncCavlc::codePredMode( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeMergeFlag ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeMergeIndex ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeInterModeFlag( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/, UInt /*uiEncMode*/ ) { assert(0); } Void TEncCavlc::codeCUTransquantBypassFlag( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeSkipFlag( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeSplitFlag ( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, UInt /*uiDepth*/ ) { assert(0); } Void TEncCavlc::codeTransformSubdivFlag( UInt /*uiSymbol*/, UInt /*uiCtx*/ ) { assert(0); } Void TEncCavlc::codeQtCbf( TComTU& /*rTu*/, const ComponentID /*compID*/, const Bool /*lowestLevel*/ ) { assert(0); } Void TEncCavlc::codeQtRootCbf( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeQtCbfZero( TComTU& /*rTu*/, const ChannelType /*chType*/ ) { assert(0); } Void TEncCavlc::codeQtRootCbfZero( ) { assert(0); } Void TEncCavlc::codeTransformSkipFlags (TComTU& /*rTu*/, ComponentID /*component*/ ) { assert(0); } /** Code I_PCM information. * \param pcCU pointer to CU * \param uiAbsPartIdx CU index * \returns Void */ Void TEncCavlc::codeIPCMInfo( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeIntraDirLumaAng( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, Bool /*isMultiple*/) { assert(0); } Void TEncCavlc::codeIntraDirChroma( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeInterDir( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeRefFrmIdx( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, RefPicList /*eRefList*/ ) { assert(0); } Void TEncCavlc::codeMvd( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/, RefPicList /*eRefList*/ ) { assert(0); } Void TEncCavlc::codeCrossComponentPrediction( TComTU& /*rTu*/, ComponentID /*compID*/ ) { assert(0); } Void TEncCavlc::codeDeltaQP( TComDataCU* pcCU, UInt uiAbsPartIdx ) { Int iDQp = pcCU->getQP( uiAbsPartIdx ) - pcCU->getRefQP( uiAbsPartIdx ); Int qpBdOffsetY = pcCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA); iDQp = (iDQp + 78 + qpBdOffsetY + (qpBdOffsetY/2)) % (52 + qpBdOffsetY) - 26 - (qpBdOffsetY/2); xWriteSvlc( iDQp ); return; } Void TEncCavlc::codeChromaQpAdjustment( TComDataCU* /*pcCU*/, UInt /*uiAbsPartIdx*/ ) { assert(0); } Void TEncCavlc::codeCoeffNxN ( TComTU& /*rTu*/, TCoeff* /*pcCoef*/, const ComponentID /*compID*/ ) { assert(0); } Void TEncCavlc::estBit( estBitsSbacStruct* /*pcEstBitsCabac*/, Int /*width*/, Int /*height*/, ChannelType /*chType*/, COEFF_SCAN_TYPE /*scanType*/ ) { // printf("error : no VLC mode support in this version\n"); return; } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== //! Code weighted prediction tables Void TEncCavlc::xCodePredWeightTable( TComSlice* pcSlice ) { WPScalingParam *wp; const ChromaFormat format = pcSlice->getPic()->getChromaFormat(); const UInt numberValidComponents = getNumberValidComponents(format); const Bool bChroma = isChromaEnabled(format); const Int iNbRef = (pcSlice->getSliceType() == B_SLICE ) ? (2) : (1); Bool bDenomCoded = false; UInt uiTotalSignalledWeightFlags = 0; if ( (pcSlice->getSliceType()==P_SLICE && pcSlice->getPPS()->getUseWP()) || (pcSlice->getSliceType()==B_SLICE && pcSlice->getPPS()->getWPBiPred()) ) { for ( Int iNumRef=0 ; iNumRefgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); if ( !bDenomCoded ) { Int iDeltaDenom; WRITE_UVLC( wp[COMPONENT_Y].uiLog2WeightDenom, "luma_log2_weight_denom" ); if( bChroma ) { assert(wp[COMPONENT_Cb].uiLog2WeightDenom == wp[COMPONENT_Cr].uiLog2WeightDenom); // check the channel-type settings are consistent across components. iDeltaDenom = (wp[COMPONENT_Cb].uiLog2WeightDenom - wp[COMPONENT_Y].uiLog2WeightDenom); WRITE_SVLC( iDeltaDenom, "delta_chroma_log2_weight_denom" ); } bDenomCoded = true; } WRITE_FLAG( wp[COMPONENT_Y].bPresentFlag, iNumRef==0?"luma_weight_l0_flag[i]":"luma_weight_l1_flag[i]" ); uiTotalSignalledWeightFlags += wp[COMPONENT_Y].bPresentFlag; } if (bChroma) { for ( Int iRefIdx=0 ; iRefIdxgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); assert(wp[COMPONENT_Cb].bPresentFlag == wp[COMPONENT_Cr].bPresentFlag); // check the channel-type settings are consistent across components. WRITE_FLAG( wp[COMPONENT_Cb].bPresentFlag, iNumRef==0?"chroma_weight_l0_flag[i]":"chroma_weight_l1_flag[i]" ); uiTotalSignalledWeightFlags += 2*wp[COMPONENT_Cb].bPresentFlag; } } for ( Int iRefIdx=0 ; iRefIdxgetNumRefIdx(eRefPicList) ; iRefIdx++ ) { pcSlice->getWpScaling(eRefPicList, iRefIdx, wp); if ( wp[COMPONENT_Y].bPresentFlag ) { Int iDeltaWeight = (wp[COMPONENT_Y].iWeight - (1<getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag() ? (1<getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA))/2 : 128; Int pred = ( range - ( ( range*wp[j].iWeight)>>(wp[j].uiLog2WeightDenom) ) ); Int iDeltaChroma = (wp[j].iOffset - pred); WRITE_SVLC( iDeltaChroma, iNumRef==0?"delta_chroma_offset_l0[i]":"delta_chroma_offset_l1[i]" ); } } } } } assert(uiTotalSignalledWeightFlags<=24); } } /** code quantization matrix * \param scalingList quantization matrix information */ Void TEncCavlc::codeScalingList( const TComScalingList &scalingList ) { //for each size for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { const Int predListStep = (sizeId == SCALING_LIST_32x32? (SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) : 1); // if 32x32, skip over chroma entries. for(UInt listId = 0; listId < SCALING_LIST_NUM; listId+=predListStep) { Bool scalingListPredModeFlag = scalingList.getScalingListPredModeFlag(sizeId, listId); WRITE_FLAG( scalingListPredModeFlag, "scaling_list_pred_mode_flag" ); if(!scalingListPredModeFlag)// Copy Mode { if (sizeId == SCALING_LIST_32x32) { // adjust the code, to cope with the missing chroma entries WRITE_UVLC( ((Int)listId - (Int)scalingList.getRefMatrixId (sizeId,listId)) / (SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES), "scaling_list_pred_matrix_id_delta"); } else { WRITE_UVLC( (Int)listId - (Int)scalingList.getRefMatrixId (sizeId,listId), "scaling_list_pred_matrix_id_delta"); } } else// DPCM Mode { xCodeScalingList(&scalingList, sizeId, listId); } } } return; } /** code DPCM * \param scalingList quantization matrix information * \param sizeId size index * \param listId list index */ Void TEncCavlc::xCodeScalingList(const TComScalingList* scalingList, UInt sizeId, UInt listId) { Int coefNum = min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId]); UInt* scan = g_scanOrder[SCAN_UNGROUPED][SCAN_DIAG][sizeId==0 ? 2 : 3][sizeId==0 ? 2 : 3]; Int nextCoef = SCALING_LIST_START_VALUE; Int data; const Int *src = scalingList->getScalingListAddress(sizeId, listId); if( sizeId > SCALING_LIST_8x8 ) { WRITE_SVLC( scalingList->getScalingListDC(sizeId,listId) - 8, "scaling_list_dc_coef_minus8"); nextCoef = scalingList->getScalingListDC(sizeId,listId); } for(Int i=0;i 127) { data = data - 256; } if(data < -128) { data = data + 256; } WRITE_SVLC( data, "scaling_list_delta_coef"); } } Bool TEncCavlc::findMatchingLTRP ( TComSlice* pcSlice, UInt *ltrpsIndex, Int ltrpPOC, Bool usedFlag ) { // Bool state = true, state2 = false; Int lsb = ltrpPOC & ((1<getSPS()->getBitsForPOC())-1); for (Int k = 0; k < pcSlice->getSPS()->getNumLongTermRefPicSPS(); k++) { if ( (lsb == pcSlice->getSPS()->getLtRefPicPocLsbSps(k)) && (usedFlag == pcSlice->getSPS()->getUsedByCurrPicLtSPSFlag(k)) ) { *ltrpsIndex = k; return true; } } return false; } Void TEncCavlc::codeExplicitRdpcmMode( TComTU& /*rTu*/, const ComponentID /*compID*/ ) { assert(0); } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncCavlc.h000066400000000000000000000153311442026013100203570ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncCavlc.h \brief CAVLC encoder class (header) */ #ifndef __TENCCAVLC__ #define __TENCCAVLC__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/TComRom.h" #include "TEncEntropy.h" #include "SyntaxElementWriter.h" //! \ingroup TLibEncoder //! \{ class TEncTop; // ==================================================================================================================== // Class definition // ==================================================================================================================== class AUDWriter : public SyntaxElementWriter { public: AUDWriter() {}; virtual ~AUDWriter() {}; Void codeAUD(TComBitIf& bs, const Int pictureType); }; /// CAVLC encoder class class TEncCavlc : public SyntaxElementWriter, public TEncEntropyIf { public: TEncCavlc(); virtual ~TEncCavlc(); protected: Void codeShortTermRefPicSet ( const TComReferencePictureSet* pcRPS, Bool calledFromSliceHeader, Int idx ); Bool findMatchingLTRP ( TComSlice* pcSlice, UInt *ltrpsIndex, Int ltrpPOC, Bool usedFlag ); public: Void resetEntropy (const TComSlice *pSlice); SliceType determineCabacInitIdx (const TComSlice* /*pSlice*/) { assert(0); return I_SLICE; }; Void setBitstream ( TComBitIf* p ) { m_pcBitIf = p; } Void resetBits () { m_pcBitIf->resetBits(); } UInt getNumberOfWrittenBits() { return m_pcBitIf->getNumberOfWrittenBits(); } Void codeVPS ( const TComVPS* pcVPS ); Void codeVUI ( const TComVUI *pcVUI, const TComSPS* pcSPS ); Void codeSPS ( const TComSPS* pcSPS ); Void codePPS ( const TComPPS* pcPPS ); Void codeSliceHeader ( TComSlice* pcSlice ); Void codePTL ( const TComPTL* pcPTL, Bool profilePresentFlag, Int maxNumSubLayersMinus1); Void codeProfileTier ( const ProfileTierLevel* ptl, const Bool bIsSubLayer ); Void codeHrdParameters ( const TComHRD *hrd, Bool commonInfPresentFlag, UInt maxNumSubLayersMinus1 ); Void codeTilesWPPEntryPoint( TComSlice* pSlice ); Void codeTerminatingBit ( UInt uilsLast ); Void codeSliceFinish (); Void codeMVPIdx ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void codeSAOBlkParam(SAOBlkParam& /*saoBlkParam*/, const BitDepths& /*bitDepths*/, Bool* /*sliceEnabled*/, Bool /*leftMergeAvail*/, Bool /*aboveMergeAvail*/, Bool /*onlyEstMergeInfo*/ = false){printf("only supported in CABAC"); assert(0); exit(-1);} Void codeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeMergeIndex ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeAlfCtrlFlag ( ComponentID /*component*/, UInt /*code*/ ) {printf("Not supported\n"); assert(0);} Void codeInterModeFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiEncMode ); Void codeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void codePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Void codePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ); Void codeQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ); Void codeQtRootCbf ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeQtCbfZero ( TComTU &rTu, const ChannelType chType ); Void codeQtRootCbfZero ( ); Void codeIntraDirLumaAng( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiple); Void codeIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeInterDir ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeRefFrmIdx ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void codeMvd ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void codeCrossComponentPrediction( TComTU &rTu, ComponentID compID ); Void codeDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void codeCoeffNxN ( TComTU &rTu, TCoeff* pcCoef, const ComponentID compID ); Void codeTransformSkipFlags ( TComTU &rTu, ComponentID component ); Void estBit ( estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType, COEFF_SCAN_TYPE scanType ); Void xCodePredWeightTable ( TComSlice* pcSlice ); Void codeScalingList ( const TComScalingList &scalingList ); Void xCodeScalingList ( const TComScalingList* scalingList, UInt sizeId, UInt listId); Void codeExplicitRdpcmMode( TComTU &rTu, const ComponentID compID ); }; //! \} #endif // !defined(AFX_TENCCAVLC_H__EE8A0B30_945B_4169_B290_24D3AD52296F__INCLUDED_) HM-HM-18.0/source/Lib/TLibEncoder/TEncCfg.h000066400000000000000000003210341442026013100200260ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncCfg.h \brief encoder configuration class (header) */ #ifndef __TENCCFG__ #define __TENCCFG__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComSlice.h" #if JVET_T0050_ANNOTATED_REGIONS_SEI #include "TLibCommon/SEI.h" #endif #include struct GOPEntry { Int m_POC; Int m_QPOffset; Double m_QPOffsetModelOffset; Double m_QPOffsetModelScale; Int m_CbQPoffset; Int m_CrQPoffset; Double m_QPFactor; Int m_tcOffsetDiv2; Int m_betaOffsetDiv2; Int m_temporalId; Bool m_refPic; Int m_numRefPicsActive; SChar m_sliceType; Int m_numRefPics; Int m_referencePics[MAX_NUM_REF_PICS]; Int m_usedByCurrPic[MAX_NUM_REF_PICS]; Int m_interRPSPrediction; Int m_deltaRPS; Int m_numRefIdc; Int m_refIdc[MAX_NUM_REF_PICS+1]; Bool m_isEncoded; GOPEntry() : m_POC(-1) , m_QPOffset(0) , m_QPOffsetModelOffset(0) , m_QPOffsetModelScale(0) , m_CbQPoffset(0) , m_CrQPoffset(0) , m_QPFactor(0) , m_tcOffsetDiv2(0) , m_betaOffsetDiv2(0) , m_temporalId(0) , m_refPic(false) , m_numRefPicsActive(0) , m_sliceType('P') , m_numRefPics(0) , m_interRPSPrediction(false) , m_deltaRPS(0) , m_numRefIdc(0) , m_isEncoded(false) { ::memset( m_referencePics, 0, sizeof(m_referencePics) ); ::memset( m_usedByCurrPic, 0, sizeof(m_usedByCurrPic) ); ::memset( m_refIdc, 0, sizeof(m_refIdc) ); } }; std::istringstream &operator>>(std::istringstream &in, GOPEntry &entry); //input //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// encoder configuration class class TEncCfg { public: struct TEncSEIKneeFunctionInformation { struct KneePointPair { Int inputKneePoint; Int outputKneePoint; }; Int m_kneeFunctionId; Bool m_kneeFunctionCancelFlag; Bool m_kneeFunctionPersistenceFlag; Int m_inputDRange; Int m_inputDispLuminance; Int m_outputDRange; Int m_outputDispLuminance; std::vector m_kneeSEIKneePointPairs; }; #if JVET_T0050_ANNOTATED_REGIONS_SEI std::map m_arObjects; #endif protected: //==== File I/O ======== Int m_iFrameRate; Int m_FrameSkip; UInt m_temporalSubsampleRatio; Int m_iSourceWidth; Int m_iSourceHeight; Window m_conformanceWindow; Int m_framesToBeEncoded; Double m_adLambdaModifier[ MAX_TLAYER ]; std::vector m_adIntraLambdaModifier; Double m_dIntraQpFactor; ///< Intra Q Factor. If negative, use a default equation: 0.57*(1.0 - Clip3( 0.0, 0.5, 0.05*(Double)(isField ? (GopSize-1)/2 : GopSize-1) )) Bool m_printMSEBasedSequencePSNR; Bool m_printHexPsnr; Bool m_printFrameMSE; Bool m_printSequenceMSE; Bool m_printMSSSIM; Bool m_bXPSNREnableFlag; Double m_dXPSNRWeight[MAX_NUM_COMPONENT]; Bool m_cabacZeroWordPaddingEnabled; #if SHUTTER_INTERVAL_SEI_PROCESSING Bool m_ShutterFilterEnable; ///< enable Pre-Filtering with Shutter Interval SEI #endif /* profile & level */ Profile::Name m_profile; Level::Tier m_levelTier; Level::Name m_level; Bool m_progressiveSourceFlag; Bool m_interlacedSourceFlag; Bool m_nonPackedConstraintFlag; Bool m_frameOnlyConstraintFlag; UInt m_bitDepthConstraintValue; ChromaFormat m_chromaFormatConstraintValue; Bool m_intraConstraintFlag; Bool m_onePictureOnlyConstraintFlag; Bool m_lowerBitRateConstraintFlag; //====== Coding Structure ======== UInt m_uiIntraPeriod; // TODO: make this an Int - it can be -1! UInt m_uiDecodingRefreshType; ///< the type of decoding refresh employed for the random access. Bool m_bReWriteParamSetsFlag; Int m_iGOPSize; GOPEntry m_GOPList[MAX_GOP]; Int m_extraRPSs; Int m_maxDecPicBuffering[MAX_TLAYER]; Int m_numReorderPics[MAX_TLAYER]; Int m_iQP; // if (AdaptiveQP == OFF) Int m_intraQPOffset; ///< QP offset for intra slice (integer) Int m_lambdaFromQPEnable; ///< enable lambda derivation from QP Int m_sourcePadding[2]; Bool m_AccessUnitDelimiter; ///< add Access Unit Delimiter NAL units Int m_iMaxRefPicNum; ///< this is used to mimic the sliding mechanism used by the decoder // TODO: We need to have a common sliding mechanism used by both the encoder and decoder Int m_maxTempLayer; ///< Max temporal layer Bool m_useAMP; UInt m_maxCUWidth; UInt m_maxCUHeight; UInt m_maxTotalCUDepth; UInt m_log2DiffMaxMinCodingBlockSize; //======= Transform ============= UInt m_uiQuadtreeTULog2MaxSize; UInt m_uiQuadtreeTULog2MinSize; UInt m_uiQuadtreeTUMaxDepthInter; UInt m_uiQuadtreeTUMaxDepthIntra; //====== Loop/Deblock Filter ======== Bool m_bLoopFilterDisable; Bool m_loopFilterOffsetInPPS; Int m_loopFilterBetaOffsetDiv2; Int m_loopFilterTcOffsetDiv2; Int m_deblockingFilterMetric; Bool m_bUseSAO; Bool m_bTestSAODisableAtPictureLevel; Double m_saoEncodingRate; // When non-0 SAO early picture termination is enabled for luma and chroma Double m_saoEncodingRateChroma; // The SAO early picture termination rate to use for chroma (when m_SaoEncodingRate is >0). If <=0, use results for luma. Int m_maxNumOffsetsPerPic; Bool m_saoCtuBoundary; Bool m_resetEncoderStateAfterIRAP; //====== Motion search ======== Bool m_bDisableIntraPUsInInterSlices; MESearchMethod m_motionEstimationSearchMethod; Int m_iSearchRange; // 0:Full frame Int m_bipredSearchRange; Bool m_bClipForBiPredMeEnabled; Bool m_bFastMEAssumingSmootherMVEnabled; Int m_minSearchWindow; Bool m_bRestrictMESampling; //====== Quality control ======== Int m_iMaxDeltaQP; // Max. absolute delta QP (1:default) Int m_iMaxCuDQPDepth; // Max. depth for a minimum CuDQP (0:default) Int m_diffCuChromaQpOffsetDepth; ///< If negative, then do not apply chroma qp offsets. Int m_chromaCbQpOffset; // Chroma Cb QP Offset (0:default) Int m_chromaCrQpOffset; // Chroma Cr Qp Offset (0:default) WCGChromaQPControl m_wcgChromaQpControl; ///< Wide-colour-gamut chroma QP control. UInt m_sliceChromaQpOffsetPeriodicity; ///< Used in conjunction with Slice Cb/Cr QpOffsetIntraOrPeriodic. Use 0 (default) to disable periodic nature. Int m_sliceChromaQpOffsetIntraOrPeriodic[2/*Cb,Cr*/]; ///< Chroma Cb QP Offset at slice level for I slice or for periodic inter slices as defined by SliceChromaQPOffsetPeriodicity. Replaces offset in the GOP table. ChromaFormat m_chromaFormatIDC; #if ADAPTIVE_QP_SELECTION Bool m_bUseAdaptQpSelect; #endif Bool m_extendedPrecisionProcessingFlag; Bool m_highPrecisionOffsetsEnabledFlag; Bool m_bUseAdaptiveQP; Int m_iQPAdaptationRange; //====== Tool list ======== Int m_bitDepth[MAX_NUM_CHANNEL_TYPE]; #if JVET_X0048_X0103_FILM_GRAIN Int m_bitDepthInput[MAX_NUM_CHANNEL_TYPE]; #endif Bool m_bUseASR; Bool m_bUseHADME; Bool m_useRDOQ; Bool m_useRDOQTS; Bool m_useSelectiveRDOQ; UInt m_rdPenalty; FastInterSearchMode m_fastInterSearchMode; Bool m_bUseEarlyCU; Bool m_useFastDecisionForMerge; Bool m_bUseCbfFastMode; Bool m_useEarlySkipDetection; Bool m_crossComponentPredictionEnabledFlag; Bool m_reconBasedCrossCPredictionEstimate; UInt m_log2SaoOffsetScale[MAX_NUM_CHANNEL_TYPE]; Bool m_useTransformSkip; Bool m_useTransformSkipFast; UInt m_log2MaxTransformSkipBlockSize; Bool m_transformSkipRotationEnabledFlag; Bool m_transformSkipContextEnabledFlag; Bool m_persistentRiceAdaptationEnabledFlag; Bool m_cabacBypassAlignmentEnabledFlag; Bool m_rdpcmEnabledFlag[NUMBER_OF_RDPCM_SIGNALLING_MODES]; LumaLevelToDeltaQPMapping m_lumaLevelToDeltaQPMapping; ///< mapping from luma level to delta QP. Int* m_aidQP; UInt m_uiDeltaQpRD; Bool m_bFastDeltaQP; #if JVET_V0078 Bool m_bSmoothQPReductionEnable; Double m_dSmoothQPReductionThreshold; Double m_dSmoothQPReductionModelScale; Double m_dSmoothQPReductionModelOffset; Int m_iSmoothQPReductionLimit; Int m_iSmoothQPReductionPeriodicity; #endif Bool m_bUseConstrainedIntraPred; Bool m_bFastUDIUseMPMEnabled; Bool m_bFastMEForGenBLowDelayEnabled; Bool m_bUseBLambdaForNonKeyLowDelayPictures; Bool m_usePCM; Int m_PCMBitDepth[MAX_NUM_CHANNEL_TYPE]; UInt m_pcmLog2MaxSize; UInt m_uiPCMLog2MinSize; //====== Slice ======== SliceConstraint m_sliceMode; Int m_sliceArgument; //====== Dependent Slice ======== SliceConstraint m_sliceSegmentMode; Int m_sliceSegmentArgument; Bool m_bLFCrossSliceBoundaryFlag; Bool m_bPCMInputBitDepthFlag; Bool m_bPCMFilterDisableFlag; Bool m_intraSmoothingDisabledFlag; Bool m_loopFilterAcrossTilesEnabledFlag; Bool m_tileUniformSpacingFlag; Int m_iNumColumnsMinus1; Int m_iNumRowsMinus1; std::vector m_tileColumnWidth; std::vector m_tileRowHeight; Bool m_entropyCodingSyncEnabledFlag; HashType m_decodedPictureHashSEIType; Bool m_bufferingPeriodSEIEnabled; Bool m_pictureTimingSEIEnabled; Bool m_recoveryPointSEIEnabled; Bool m_toneMappingInfoSEIEnabled; Int m_toneMapId; Bool m_toneMapCancelFlag; Bool m_toneMapPersistenceFlag; Int m_codedDataBitDepth; Int m_targetBitDepth; Int m_modelId; Int m_minValue; Int m_maxValue; Int m_sigmoidMidpoint; Int m_sigmoidWidth; Int m_numPivots; Int m_cameraIsoSpeedIdc; Int m_cameraIsoSpeedValue; Int m_exposureIndexIdc; Int m_exposureIndexValue; Bool m_exposureCompensationValueSignFlag; Int m_exposureCompensationValueNumerator; Int m_exposureCompensationValueDenomIdc; Int m_refScreenLuminanceWhite; Int m_extendedRangeWhiteLevel; Int m_nominalBlackLevelLumaCodeValue; Int m_nominalWhiteLevelLumaCodeValue; Int m_extendedWhiteLevelLumaCodeValue; Int* m_startOfCodedInterval; Int* m_codedPivotValue; Int* m_targetPivotValue; Bool m_framePackingSEIEnabled; Int m_framePackingSEIType; Int m_framePackingSEIId; Int m_framePackingSEIQuincunx; Int m_framePackingSEIInterpretation; Bool m_segmentedRectFramePackingSEIEnabled; Bool m_segmentedRectFramePackingSEICancel; Int m_segmentedRectFramePackingSEIType; Bool m_segmentedRectFramePackingSEIPersistence; Int m_displayOrientationSEIAngle; Bool m_temporalLevel0IndexSEIEnabled; Bool m_gradualDecodingRefreshInfoEnabled; Int m_noDisplaySEITLayer; Bool m_decodingUnitInfoSEIEnabled; Bool m_SOPDescriptionSEIEnabled; Bool m_scalableNestingSEIEnabled; Bool m_tmctsSEIEnabled; #if MCTS_ENC_CHECK Bool m_tmctsSEITileConstraint; #endif #if MCTS_EXTRACTION Bool m_tmctsExtractionSEIEnabled; #endif Bool m_timeCodeSEIEnabled; Int m_timeCodeSEINumTs; TComSEITimeSet m_timeSetArray[MAX_TIMECODE_SEI_SETS]; Bool m_kneeSEIEnabled; TEncSEIKneeFunctionInformation m_kneeFunctionInformationSEI; std::string m_colourRemapSEIFileRoot; ///< SEI Colour Remapping File (initialized from external file) TComSEIMasteringDisplay m_masteringDisplay; Bool m_alternativeTransferCharacteristicsSEIEnabled; UChar m_preferredTransferCharacteristics; Bool m_greenMetadataInfoSEIEnabled; UChar m_greenMetadataType; UChar m_xsdMetricType; Bool m_ccvSEIEnabled; Bool m_ccvSEICancelFlag; Bool m_ccvSEIPersistenceFlag; Bool m_ccvSEIPrimariesPresentFlag; Bool m_ccvSEIMinLuminanceValuePresentFlag; Bool m_ccvSEIMaxLuminanceValuePresentFlag; Bool m_ccvSEIAvgLuminanceValuePresentFlag; Double m_ccvSEIPrimariesX[MAX_NUM_COMPONENT]; Double m_ccvSEIPrimariesY[MAX_NUM_COMPONENT]; Double m_ccvSEIMinLuminanceValue; Double m_ccvSEIMaxLuminanceValue; Double m_ccvSEIAvgLuminanceValue; Bool m_erpSEIEnabled; Bool m_erpSEICancelFlag; Bool m_erpSEIPersistenceFlag; Bool m_erpSEIGuardBandFlag; UInt m_erpSEIGuardBandType; UInt m_erpSEILeftGuardBandWidth; UInt m_erpSEIRightGuardBandWidth; Bool m_sphereRotationSEIEnabled; Bool m_sphereRotationSEICancelFlag; Bool m_sphereRotationSEIPersistenceFlag; Int m_sphereRotationSEIYaw; Int m_sphereRotationSEIPitch; Int m_sphereRotationSEIRoll; Bool m_omniViewportSEIEnabled; UInt m_omniViewportSEIId; Bool m_omniViewportSEICancelFlag; Bool m_omniViewportSEIPersistenceFlag; UInt m_omniViewportSEICntMinus1; std::vector m_omniViewportSEIAzimuthCentre; std::vector m_omniViewportSEIElevationCentre; std::vector m_omniViewportSEITiltCentre; std::vector m_omniViewportSEIHorRange; std::vector m_omniViewportSEIVerRange; Bool m_gopBasedTemporalFilterEnabled; #if JVET_Y0077_BIM Bool m_bimEnabled; std::map m_adaptQPmap; #endif Bool m_cmpSEIEnabled; Bool m_cmpSEICmpCancelFlag; Bool m_cmpSEICmpPersistenceFlag; Bool m_rwpSEIEnabled; Bool m_rwpSEIRwpCancelFlag; Bool m_rwpSEIRwpPersistenceFlag; Bool m_rwpSEIConstituentPictureMatchingFlag; Int m_rwpSEINumPackedRegions; Int m_rwpSEIProjPictureWidth; Int m_rwpSEIProjPictureHeight; Int m_rwpSEIPackedPictureWidth; Int m_rwpSEIPackedPictureHeight; std::vector m_rwpSEIRwpTransformType; std::vector m_rwpSEIRwpGuardBandFlag; std::vector m_rwpSEIProjRegionWidth; std::vector m_rwpSEIProjRegionHeight; std::vector m_rwpSEIRwpSEIProjRegionTop; std::vector m_rwpSEIProjRegionLeft; std::vector m_rwpSEIPackedRegionWidth; std::vector m_rwpSEIPackedRegionHeight; std::vector m_rwpSEIPackedRegionTop; std::vector m_rwpSEIPackedRegionLeft; std::vector m_rwpSEIRwpLeftGuardBandWidth; std::vector m_rwpSEIRwpRightGuardBandWidth; std::vector m_rwpSEIRwpTopGuardBandHeight; std::vector m_rwpSEIRwpBottomGuardBandHeight; std::vector m_rwpSEIRwpGuardBandNotUsedForPredFlag; std::vector m_rwpSEIRwpGuardBandType; std::string m_arSEIFileRoot; // Annotated region SEI - initialized from external file Bool m_fviSEIEnabled; TComSEIFisheyeVideoInfo m_fisheyeVideoInfo; std::string m_regionalNestingSEIFileRoot; // Regional nesting SEI - initialized from external file #if SHUTTER_INTERVAL_SEI_MESSAGE Bool m_siiSEIEnabled; UInt m_siiSEINumUnitsInShutterInterval; UInt m_siiSEITimeScale; std::vector m_siiSEISubLayerNumUnitsInSI; #endif #if SEI_ENCODER_CONTROL // film grain characterstics sei Bool m_fgcSEIEnabled; Bool m_fgcSEICancelFlag; Bool m_fgcSEIPersistenceFlag; UChar m_fgcSEIModelID; Bool m_fgcSEISepColourDescPresentFlag; UChar m_fgcSEIBlendingModeID; UChar m_fgcSEILog2ScaleFactor; Bool m_fgcSEICompModelPresent[MAX_NUM_COMPONENT]; #if JVET_X0048_X0103_FILM_GRAIN Bool m_fgcSEIAnalysisEnabled; std::string m_fgcSEIExternalMask; std::string m_fgcSEIExternalDenoised; Bool m_fgcSEIPerPictureSEI; UChar m_fgcSEINumIntensityIntervalMinus1[MAX_NUM_COMPONENT]; UChar m_fgcSEINumModelValuesMinus1[MAX_NUM_COMPONENT]; UChar m_fgcSEIIntensityIntervalLowerBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UChar m_fgcSEIIntensityIntervalUpperBound[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES]; UInt m_fgcSEICompModelValue[MAX_NUM_COMPONENT][FG_MAX_NUM_INTENSITIES][FG_MAX_NUM_MODEL_VALUES]; #endif // content light level SEI Bool m_cllSEIEnabled; UShort m_cllSEIMaxContentLevel; UShort m_cllSEIMaxPicAvgLevel; // ambient viewing environment sei Bool m_aveSEIEnabled; UInt m_aveSEIAmbientIlluminance; UShort m_aveSEIAmbientLightX; UShort m_aveSEIAmbientLightY; #endif //====== Weighted Prediction ======== Bool m_useWeightedPred; //< Use of Weighting Prediction (P_SLICE) Bool m_useWeightedBiPred; //< Use of Bi-directional Weighting Prediction (B_SLICE) WeightedPredictionMethod m_weightedPredictionMethod; UInt m_log2ParallelMergeLevelMinus2; ///< Parallel merge estimation region UInt m_maxNumMergeCand; ///< Maximum number of merge candidates ScalingListMode m_useScalingListId; ///< Using quantization matrix i.e. 0=off, 1=default, 2=file. std::string m_scalingListFileName; ///< quantization matrix file name Int m_TMVPModeId; Bool m_SignDataHidingEnabledFlag; Bool m_RCEnableRateControl; Int m_RCTargetBitrate; Int m_RCKeepHierarchicalBit; Bool m_RCLCULevelRC; Bool m_RCUseLCUSeparateModel; Int m_RCInitialQP; Bool m_RCForceIntraQP; Bool m_RCCpbSaturationEnabled; UInt m_RCCpbSize; Double m_RCInitialCpbFullness; Bool m_TransquantBypassEnabledFlag; ///< transquant_bypass_enabled_flag setting in PPS. Bool m_CUTransquantBypassFlagForce; ///< if transquant_bypass_enabled_flag, then, if true, all CU transquant bypass flags will be set to true. CostMode m_costMode; ///< The cost function to use, primarily when considering lossless coding. TComVPS m_cVPS; Bool m_recalculateQPAccordingToLambda; ///< recalculate QP value according to the lambda value Int m_activeParameterSetsSEIEnabled; ///< enable active parameter set SEI message Bool m_vuiParametersPresentFlag; ///< enable generation of VUI parameters Bool m_aspectRatioInfoPresentFlag; ///< Signals whether aspect_ratio_idc is present Bool m_chromaResamplingFilterHintEnabled; ///< Signals whether chroma sampling filter hint data is present Int m_chromaResamplingHorFilterIdc; ///< Specifies the Index of filter to use Int m_chromaResamplingVerFilterIdc; ///< Specifies the Index of filter to use Int m_aspectRatioIdc; ///< aspect_ratio_idc Int m_sarWidth; ///< horizontal size of the sample aspect ratio Int m_sarHeight; ///< vertical size of the sample aspect ratio Bool m_overscanInfoPresentFlag; ///< Signals whether overscan_appropriate_flag is present Bool m_overscanAppropriateFlag; ///< Indicates whether conformant decoded pictures are suitable for display using overscan Bool m_videoSignalTypePresentFlag; ///< Signals whether video_format, video_full_range_flag, and colour_description_present_flag are present Int m_videoFormat; ///< Indicates representation of pictures Bool m_videoFullRangeFlag; ///< Indicates the black level and range of luma and chroma signals Bool m_colourDescriptionPresentFlag; ///< Signals whether colour_primaries, transfer_characteristics and matrix_coefficients are present Int m_colourPrimaries; ///< Indicates chromaticity coordinates of the source primaries Int m_transferCharacteristics; ///< Indicates the opto-electronic transfer characteristics of the source Int m_matrixCoefficients; ///< Describes the matrix coefficients used in deriving luma and chroma from RGB primaries Bool m_chromaLocInfoPresentFlag; ///< Signals whether chroma_sample_loc_type_top_field and chroma_sample_loc_type_bottom_field are present Int m_chromaSampleLocTypeTopField; ///< Specifies the location of chroma samples for top field Int m_chromaSampleLocTypeBottomField; ///< Specifies the location of chroma samples for bottom field Bool m_neutralChromaIndicationFlag; ///< Indicates that the value of all decoded chroma samples is equal to 1<<(BitDepthCr-1) Window m_defaultDisplayWindow; ///< Represents the default display window parameters Bool m_frameFieldInfoPresentFlag; ///< Indicates that pic_struct and other field coding related values are present in picture timing SEI messages Bool m_pocProportionalToTimingFlag; ///< Indicates that the POC value is proportional to the output time w.r.t. first picture in CVS Int m_numTicksPocDiffOneMinus1; ///< Number of ticks minus 1 that for a POC difference of one Bool m_bitstreamRestrictionFlag; ///< Signals whether bitstream restriction parameters are present Bool m_tilesFixedStructureFlag; ///< Indicates that each active picture parameter set has the same values of the syntax elements related to tiles Bool m_motionVectorsOverPicBoundariesFlag; ///< Indicates that no samples outside the picture boundaries are used for inter prediction Int m_minSpatialSegmentationIdc; ///< Indicates the maximum size of the spatial segments in the pictures in the coded video sequence Int m_maxBytesPerPicDenom; ///< Indicates a number of bytes not exceeded by the sum of the sizes of the VCL NAL units associated with any coded picture Int m_maxBitsPerMinCuDenom; ///< Indicates an upper bound for the number of bits of coding_unit() data Int m_log2MaxMvLengthHorizontal; ///< Indicate the maximum absolute value of a decoded horizontal MV component in quarter-pel luma units Int m_log2MaxMvLengthVertical; ///< Indicate the maximum absolute value of a decoded vertical MV component in quarter-pel luma units Bool m_useStrongIntraSmoothing; ///< enable the use of strong intra smoothing (bi_linear interpolation) for 32x32 blocks when reference samples are flat. Bool m_bEfficientFieldIRAPEnabled; ///< enable to code fields in a specific, potentially more efficient, order. Bool m_bHarmonizeGopFirstFieldCoupleEnabled; std::string m_summaryOutFilename; ///< filename to use for producing summary output file. std::string m_summaryPicFilenameBase; ///< Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended. UInt m_summaryVerboseness; ///< Specifies the level of the verboseness of the text output. #if JCTVC_AD0021_SEI_MANIFEST Bool m_SEIManifestSEIEnabled; #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Bool m_SEIPrefixIndicationSEIEnabled; #endif public: TEncCfg() : m_tileColumnWidth() , m_tileRowHeight() { m_PCMBitDepth[CHANNEL_TYPE_LUMA]=8; m_PCMBitDepth[CHANNEL_TYPE_CHROMA]=8; } virtual ~TEncCfg() {} Void setProfile(Profile::Name profile) { m_profile = profile; } Void setLevel(Level::Tier tier, Level::Name level) { m_levelTier = tier; m_level = level; } Void setFrameRate ( Int i ) { m_iFrameRate = i; } Void setFrameSkip ( UInt i ) { m_FrameSkip = i; } Void setTemporalSubsampleRatio ( UInt i ) { m_temporalSubsampleRatio = i; } Void setSourceWidth ( Int i ) { m_iSourceWidth = i; } Void setSourceHeight ( Int i ) { m_iSourceHeight = i; } Window &getConformanceWindow() { return m_conformanceWindow; } Void setConformanceWindow (Int confLeft, Int confRight, Int confTop, Int confBottom ) { m_conformanceWindow.setWindow (confLeft, confRight, confTop, confBottom); } Void setFramesToBeEncoded ( Int i ) { m_framesToBeEncoded = i; } Bool getPrintMSEBasedSequencePSNR () const { return m_printMSEBasedSequencePSNR; } Void setPrintMSEBasedSequencePSNR (Bool value) { m_printMSEBasedSequencePSNR = value; } Bool getPrintHexPsnr () const { return m_printHexPsnr; } Void setPrintHexPsnr (Bool value) { m_printHexPsnr = value; } Bool getPrintFrameMSE () const { return m_printFrameMSE; } Void setPrintFrameMSE (Bool value) { m_printFrameMSE = value; } Bool getPrintSequenceMSE () const { return m_printSequenceMSE; } Void setPrintSequenceMSE (Bool value) { m_printSequenceMSE = value; } Bool getPrintMSSSIM () const { return m_printMSSSIM; } Void setPrintMSSSIM (Bool value) { m_printMSSSIM = value; } Bool getXPSNREnableFlag () const { return m_bXPSNREnableFlag;} Double getXPSNRWeight (const ComponentID id) const { return m_dXPSNRWeight[id];} Void setXPSNREnableFlag ( Bool i ) { m_bXPSNREnableFlag = i; } Void setXPSNRWeight ( Double dValue, ComponentID id) { m_dXPSNRWeight[id] = dValue;} Bool getCabacZeroWordPaddingEnabled() const { return m_cabacZeroWordPaddingEnabled; } Void setCabacZeroWordPaddingEnabled(Bool value) { m_cabacZeroWordPaddingEnabled = value; } #if SHUTTER_INTERVAL_SEI_PROCESSING Bool getShutterFilterFlag() const { return m_ShutterFilterEnable; } Void setShutterFilterFlag(Bool value) { m_ShutterFilterEnable = value; } #endif //====== Coding Structure ======== Void setIntraPeriod ( Int i ) { m_uiIntraPeriod = (UInt)i; } Void setDecodingRefreshType ( Int i ) { m_uiDecodingRefreshType = (UInt)i; } Void setReWriteParamSetsFlag ( Bool b ) { m_bReWriteParamSetsFlag = b; } Void setGOPSize ( Int i ) { m_iGOPSize = i; } Void setGopList ( const GOPEntry GOPList[MAX_GOP] ) { for ( Int i = 0; i < MAX_GOP; i++ ) m_GOPList[i] = GOPList[i]; } Void setExtraRPSs ( Int i ) { m_extraRPSs = i; } const GOPEntry &getGOPEntry ( Int i ) const { return m_GOPList[i]; } Void setEncodedFlag ( Int i, Bool value ) { m_GOPList[i].m_isEncoded = value; } Void setMaxDecPicBuffering ( UInt u, UInt tlayer ) { m_maxDecPicBuffering[tlayer] = u; } Void setNumReorderPics ( Int i, UInt tlayer ) { m_numReorderPics[tlayer] = i; } Void setQP ( Int i ) { m_iQP = i; } Void setIntraQPOffset ( Int i ) { m_intraQPOffset = i; } Void setLambdaFromQPEnable ( Bool b ) { m_lambdaFromQPEnable = b; } Void setSourcePadding ( Int* padding ) { for ( Int i = 0; i < 2; i++ ) m_sourcePadding[i] = padding[i]; } Int getMaxRefPicNum () { return m_iMaxRefPicNum; } Void setMaxRefPicNum ( Int iMaxRefPicNum ) { m_iMaxRefPicNum = iMaxRefPicNum; } Int getMaxTempLayer () { return m_maxTempLayer; } Void setMaxTempLayer ( Int maxTempLayer ) { m_maxTempLayer = maxTempLayer; } Void setMaxCUWidth ( UInt u ) { m_maxCUWidth = u; } Void setMaxCUHeight ( UInt u ) { m_maxCUHeight = u; } Void setMaxTotalCUDepth ( UInt u ) { m_maxTotalCUDepth = u; } Void setLog2DiffMaxMinCodingBlockSize( UInt u ) { m_log2DiffMaxMinCodingBlockSize = u; } //======== Transform ============= Void setQuadtreeTULog2MaxSize ( UInt u ) { m_uiQuadtreeTULog2MaxSize = u; } Void setQuadtreeTULog2MinSize ( UInt u ) { m_uiQuadtreeTULog2MinSize = u; } Void setQuadtreeTUMaxDepthInter ( UInt u ) { m_uiQuadtreeTUMaxDepthInter = u; } Void setQuadtreeTUMaxDepthIntra ( UInt u ) { m_uiQuadtreeTUMaxDepthIntra = u; } Void setUseAMP( Bool b ) { m_useAMP = b; } //====== Loop/Deblock Filter ======== Void setLoopFilterDisable ( Bool b ) { m_bLoopFilterDisable = b; } Void setLoopFilterOffsetInPPS ( Bool b ) { m_loopFilterOffsetInPPS = b; } Void setLoopFilterBetaOffset ( Int i ) { m_loopFilterBetaOffsetDiv2 = i; } Void setLoopFilterTcOffset ( Int i ) { m_loopFilterTcOffsetDiv2 = i; } Void setDeblockingFilterMetric ( Int i ) { m_deblockingFilterMetric = i; } //====== Motion search ======== Void setDisableIntraPUsInInterSlices ( Bool b ) { m_bDisableIntraPUsInInterSlices = b; } Void setMotionEstimationSearchMethod ( MESearchMethod e ) { m_motionEstimationSearchMethod = e; } Void setSearchRange ( Int i ) { m_iSearchRange = i; } Void setBipredSearchRange ( Int i ) { m_bipredSearchRange = i; } Void setClipForBiPredMeEnabled ( Bool b ) { m_bClipForBiPredMeEnabled = b; } Void setFastMEAssumingSmootherMVEnabled ( Bool b ) { m_bFastMEAssumingSmootherMVEnabled = b; } Void setMinSearchWindow ( Int i ) { m_minSearchWindow = i; } Void setRestrictMESampling ( Bool b ) { m_bRestrictMESampling = b; } //====== Quality control ======== Void setMaxDeltaQP ( Int i ) { m_iMaxDeltaQP = i; } Void setMaxCuDQPDepth ( Int i ) { m_iMaxCuDQPDepth = i; } Int getDiffCuChromaQpOffsetDepth () const { return m_diffCuChromaQpOffsetDepth; } Void setDiffCuChromaQpOffsetDepth (Int value) { m_diffCuChromaQpOffsetDepth = value; } Void setChromaCbQpOffset ( Int i ) { m_chromaCbQpOffset = i; } Void setChromaCrQpOffset ( Int i ) { m_chromaCrQpOffset = i; } Void setWCGChromaQpControl ( const WCGChromaQPControl &ctrl ) { m_wcgChromaQpControl = ctrl; } const WCGChromaQPControl &getWCGChromaQPControl () const { return m_wcgChromaQpControl; } Void setSliceChromaOffsetQpIntraOrPeriodic( UInt periodicity, Int sliceChromaQpOffsetIntraOrPeriodic[2]) { m_sliceChromaQpOffsetPeriodicity = periodicity; memcpy(m_sliceChromaQpOffsetIntraOrPeriodic, sliceChromaQpOffsetIntraOrPeriodic, sizeof(m_sliceChromaQpOffsetIntraOrPeriodic)); } Int getSliceChromaOffsetQpIntraOrPeriodic( Bool bIsCr) const { return m_sliceChromaQpOffsetIntraOrPeriodic[bIsCr?1:0]; } UInt getSliceChromaOffsetQpPeriodicity() const { return m_sliceChromaQpOffsetPeriodicity; } Void setChromaFormatIdc ( ChromaFormat cf ) { m_chromaFormatIDC = cf; } ChromaFormat getChromaFormatIdc ( ) { return m_chromaFormatIDC; } Void setLumaLevelToDeltaQPControls( const LumaLevelToDeltaQPMapping &lumaLevelToDeltaQPMapping ) { m_lumaLevelToDeltaQPMapping=lumaLevelToDeltaQPMapping; } const LumaLevelToDeltaQPMapping& getLumaLevelToDeltaQPMapping() const { return m_lumaLevelToDeltaQPMapping; } #if ADAPTIVE_QP_SELECTION Void setUseAdaptQpSelect ( Bool i ) { m_bUseAdaptQpSelect = i; } Bool getUseAdaptQpSelect () { return m_bUseAdaptQpSelect; } #endif #if JVET_V0078 Bool getSmoothQPReductionEnable () const { return m_bSmoothQPReductionEnable; } void setSmoothQPReductionEnable (Bool value) { m_bSmoothQPReductionEnable = value; } Double getSmoothQPReductionThreshold () const { return m_dSmoothQPReductionThreshold; } void setSmoothQPReductionThreshold (Double value) { m_dSmoothQPReductionThreshold = value; } Double getSmoothQPReductionModelScale () const { return m_dSmoothQPReductionModelScale; } void setSmoothQPReductionModelScale (Double value) { m_dSmoothQPReductionModelScale = value; } Double getSmoothQPReductionModelOffset () const { return m_dSmoothQPReductionModelOffset; } void setSmoothQPReductionModelOffset (Double value) { m_dSmoothQPReductionModelOffset = value; } Int getSmoothQPReductionLimit () const { return m_iSmoothQPReductionLimit; } void setSmoothQPReductionLimit (Int value) { m_iSmoothQPReductionLimit = value; } Int getSmoothQPReductionPeriodicity () const { return m_iSmoothQPReductionPeriodicity; } void setSmoothQPReductionPeriodicity (Int value) { m_iSmoothQPReductionPeriodicity = value; } #endif Bool getExtendedPrecisionProcessingFlag () const { return m_extendedPrecisionProcessingFlag; } Void setExtendedPrecisionProcessingFlag (Bool value) { m_extendedPrecisionProcessingFlag = value; } Bool getHighPrecisionOffsetsEnabledFlag() const { return m_highPrecisionOffsetsEnabledFlag; } Void setHighPrecisionOffsetsEnabledFlag(Bool value) { m_highPrecisionOffsetsEnabledFlag = value; } Void setUseAdaptiveQP ( Bool b ) { m_bUseAdaptiveQP = b; } Void setQPAdaptationRange ( Int i ) { m_iQPAdaptationRange = i; } //====== Sequence ======== Int getFrameRate () { return m_iFrameRate; } UInt getFrameSkip () { return m_FrameSkip; } UInt getTemporalSubsampleRatio () { return m_temporalSubsampleRatio; } Int getSourceWidth () { return m_iSourceWidth; } Int getSourceHeight () { return m_iSourceHeight; } Int getFramesToBeEncoded () { return m_framesToBeEncoded; } //====== Lambda Modifiers ======== Void setLambdaModifier ( UInt uiIndex, Double dValue ) { m_adLambdaModifier[ uiIndex ] = dValue; } Double getLambdaModifier ( UInt uiIndex ) const { return m_adLambdaModifier[ uiIndex ]; } Void setIntraLambdaModifier ( const std::vector &dValue ) { m_adIntraLambdaModifier = dValue; } const std::vector& getIntraLambdaModifier() const { return m_adIntraLambdaModifier; } Void setIntraQpFactor ( Double dValue ) { m_dIntraQpFactor = dValue; } Double getIntraQpFactor () const { return m_dIntraQpFactor; } //==== Coding Structure ======== UInt getIntraPeriod () { return m_uiIntraPeriod; } UInt getDecodingRefreshType () { return m_uiDecodingRefreshType; } Bool getReWriteParamSetsFlag () { return m_bReWriteParamSetsFlag; } Int getGOPSize () { return m_iGOPSize; } Int getMaxDecPicBuffering (UInt tlayer) { return m_maxDecPicBuffering[tlayer]; } Int getNumReorderPics (UInt tlayer) { return m_numReorderPics[tlayer]; } Int getIntraQPOffset () const { return m_intraQPOffset; } Int getLambdaFromQPEnable () const { return m_lambdaFromQPEnable; } protected: Int getBaseQP () const { return m_iQP; } // public should use getQPForPicture. public: Int getQPForPicture (const UInt gopIndex, const TComSlice *pSlice) const; // Function actually defined in TEncTop.cpp Int getSourcePadding ( Int i ) const { assert (i < 2 ); return m_sourcePadding[i]; } Bool getAccessUnitDelimiter() const { return m_AccessUnitDelimiter; } Void setAccessUnitDelimiter(Bool val){ m_AccessUnitDelimiter = val; } //======== Transform ============= UInt getQuadtreeTULog2MaxSize () const { return m_uiQuadtreeTULog2MaxSize; } UInt getQuadtreeTULog2MinSize () const { return m_uiQuadtreeTULog2MinSize; } UInt getQuadtreeTUMaxDepthInter () const { return m_uiQuadtreeTUMaxDepthInter; } UInt getQuadtreeTUMaxDepthIntra () const { return m_uiQuadtreeTUMaxDepthIntra; } //==== Loop/Deblock Filter ======== Bool getLoopFilterDisable () { return m_bLoopFilterDisable; } Bool getLoopFilterOffsetInPPS () { return m_loopFilterOffsetInPPS; } Int getLoopFilterBetaOffset () { return m_loopFilterBetaOffsetDiv2; } Int getLoopFilterTcOffset () { return m_loopFilterTcOffsetDiv2; } Int getDeblockingFilterMetric () { return m_deblockingFilterMetric; } //==== Motion search ======== Bool getDisableIntraPUsInInterSlices () const { return m_bDisableIntraPUsInInterSlices; } MESearchMethod getMotionEstimationSearchMethod ( ) const { return m_motionEstimationSearchMethod; } Int getSearchRange () const { return m_iSearchRange; } Bool getClipForBiPredMeEnabled () const { return m_bClipForBiPredMeEnabled; } Bool getFastMEAssumingSmootherMVEnabled () const { return m_bFastMEAssumingSmootherMVEnabled; } Int getMinSearchWindow () const { return m_minSearchWindow; } Bool getRestrictMESampling () const { return m_bRestrictMESampling; } //==== Quality control ======== Int getMaxDeltaQP () const { return m_iMaxDeltaQP; } Int getMaxCuDQPDepth () const { return m_iMaxCuDQPDepth; } Bool getUseAdaptiveQP () const { return m_bUseAdaptiveQP; } Int getQPAdaptationRange () const { return m_iQPAdaptationRange; } #if JVET_X0048_X0103_FILM_GRAIN int getBitDepth(const ChannelType chType) const { return m_bitDepth[chType]; } int* getBitDepth() { return m_bitDepth; } int getBitDepthInput(const ChannelType chType) const { return m_bitDepthInput[chType]; } int* getBitDepthInput() { return m_bitDepthInput; } Void setBitDepthInput(const ChannelType chType, Int internalBitDepthForChannel) { m_bitDepthInput[chType] = internalBitDepthForChannel; } #endif //==== Tool list ======== Void setBitDepth( const ChannelType chType, Int internalBitDepthForChannel ) { m_bitDepth[chType] = internalBitDepthForChannel; } Void setUseASR ( Bool b ) { m_bUseASR = b; } Void setUseHADME ( Bool b ) { m_bUseHADME = b; } Void setUseRDOQ ( Bool b ) { m_useRDOQ = b; } Void setUseRDOQTS ( Bool b ) { m_useRDOQTS = b; } Void setUseSelectiveRDOQ ( Bool b ) { m_useSelectiveRDOQ = b; } Void setRDpenalty ( UInt u ) { m_rdPenalty = u; } Void setFastInterSearchMode ( FastInterSearchMode m ) { m_fastInterSearchMode = m; } Void setUseEarlyCU ( Bool b ) { m_bUseEarlyCU = b; } Void setUseFastDecisionForMerge ( Bool b ) { m_useFastDecisionForMerge = b; } Void setUseCbfFastMode ( Bool b ) { m_bUseCbfFastMode = b; } Void setUseEarlySkipDetection ( Bool b ) { m_useEarlySkipDetection = b; } Void setUseConstrainedIntraPred ( Bool b ) { m_bUseConstrainedIntraPred = b; } Void setFastUDIUseMPMEnabled ( Bool b ) { m_bFastUDIUseMPMEnabled = b; } Void setFastMEForGenBLowDelayEnabled ( Bool b ) { m_bFastMEForGenBLowDelayEnabled = b; } Void setUseBLambdaForNonKeyLowDelayPictures ( Bool b ) { m_bUseBLambdaForNonKeyLowDelayPictures = b; } Void setPCMInputBitDepthFlag ( Bool b ) { m_bPCMInputBitDepthFlag = b; } Void setPCMFilterDisableFlag ( Bool b ) { m_bPCMFilterDisableFlag = b; } Void setUsePCM ( Bool b ) { m_usePCM = b; } Void setPCMBitDepth( const ChannelType chType, Int pcmBitDepthForChannel ) { m_PCMBitDepth[chType] = pcmBitDepthForChannel; } Void setPCMLog2MaxSize ( UInt u ) { m_pcmLog2MaxSize = u; } Void setPCMLog2MinSize ( UInt u ) { m_uiPCMLog2MinSize = u; } Void setdQPs ( Int* p ) { m_aidQP = p; } Void setDeltaQpRD ( UInt u ) {m_uiDeltaQpRD = u; } Void setFastDeltaQp ( Bool b ) {m_bFastDeltaQP = b; } Bool getUseASR () { return m_bUseASR; } Bool getUseHADME () { return m_bUseHADME; } Bool getUseRDOQ () { return m_useRDOQ; } Bool getUseRDOQTS () { return m_useRDOQTS; } Bool getUseSelectiveRDOQ () { return m_useSelectiveRDOQ; } Int getRDpenalty () { return m_rdPenalty; } FastInterSearchMode getFastInterSearchMode() const{ return m_fastInterSearchMode; } Bool getUseEarlyCU () { return m_bUseEarlyCU; } Bool getUseFastDecisionForMerge () { return m_useFastDecisionForMerge; } Bool getUseCbfFastMode () { return m_bUseCbfFastMode; } Bool getUseEarlySkipDetection () { return m_useEarlySkipDetection; } Bool getUseConstrainedIntraPred () { return m_bUseConstrainedIntraPred; } Bool getFastUDIUseMPMEnabled () { return m_bFastUDIUseMPMEnabled; } Bool getFastMEForGenBLowDelayEnabled () { return m_bFastMEForGenBLowDelayEnabled; } Bool getUseBLambdaForNonKeyLowDelayPictures () { return m_bUseBLambdaForNonKeyLowDelayPictures; } Bool getPCMInputBitDepthFlag () { return m_bPCMInputBitDepthFlag; } Bool getPCMFilterDisableFlag () { return m_bPCMFilterDisableFlag; } Bool getUsePCM () { return m_usePCM; } UInt getPCMLog2MaxSize () { return m_pcmLog2MaxSize; } UInt getPCMLog2MinSize () { return m_uiPCMLog2MinSize; } Bool getCrossComponentPredictionEnabledFlag () const { return m_crossComponentPredictionEnabledFlag; } Void setCrossComponentPredictionEnabledFlag (const Bool value) { m_crossComponentPredictionEnabledFlag = value; } Bool getUseReconBasedCrossCPredictionEstimate () const { return m_reconBasedCrossCPredictionEstimate; } Void setUseReconBasedCrossCPredictionEstimate (const Bool value) { m_reconBasedCrossCPredictionEstimate = value; } Void setLog2SaoOffsetScale(ChannelType type, UInt uiBitShift) { m_log2SaoOffsetScale[type] = uiBitShift; } Bool getUseTransformSkip () { return m_useTransformSkip; } Void setUseTransformSkip ( Bool b ) { m_useTransformSkip = b; } Bool getTransformSkipRotationEnabledFlag () const { return m_transformSkipRotationEnabledFlag; } Void setTransformSkipRotationEnabledFlag (const Bool value) { m_transformSkipRotationEnabledFlag = value; } Bool getTransformSkipContextEnabledFlag () const { return m_transformSkipContextEnabledFlag; } Void setTransformSkipContextEnabledFlag (const Bool value) { m_transformSkipContextEnabledFlag = value; } Bool getPersistentRiceAdaptationEnabledFlag () const { return m_persistentRiceAdaptationEnabledFlag; } Void setPersistentRiceAdaptationEnabledFlag (const Bool value) { m_persistentRiceAdaptationEnabledFlag = value; } Bool getCabacBypassAlignmentEnabledFlag () const { return m_cabacBypassAlignmentEnabledFlag; } Void setCabacBypassAlignmentEnabledFlag (const Bool value) { m_cabacBypassAlignmentEnabledFlag = value; } Bool getRdpcmEnabledFlag (const RDPCMSignallingMode signallingMode) const { return m_rdpcmEnabledFlag[signallingMode]; } Void setRdpcmEnabledFlag (const RDPCMSignallingMode signallingMode, const Bool value) { m_rdpcmEnabledFlag[signallingMode] = value; } Bool getUseTransformSkipFast () { return m_useTransformSkipFast; } Void setUseTransformSkipFast ( Bool b ) { m_useTransformSkipFast = b; } UInt getLog2MaxTransformSkipBlockSize () const { return m_log2MaxTransformSkipBlockSize; } Void setLog2MaxTransformSkipBlockSize ( UInt u ) { m_log2MaxTransformSkipBlockSize = u; } Bool getIntraSmoothingDisabledFlag () const { return m_intraSmoothingDisabledFlag; } Void setIntraSmoothingDisabledFlag (Bool bValue) { m_intraSmoothingDisabledFlag=bValue; } const Int* getdQPs () const { return m_aidQP; } UInt getDeltaQpRD () const { return m_uiDeltaQpRD; } Bool getFastDeltaQp () const { return m_bFastDeltaQP; } //====== Slice ======== Void setSliceMode ( SliceConstraint i ) { m_sliceMode = i; } Void setSliceArgument ( Int i ) { m_sliceArgument = i; } SliceConstraint getSliceMode () const { return m_sliceMode; } Int getSliceArgument () { return m_sliceArgument; } //====== Dependent Slice ======== Void setSliceSegmentMode ( SliceConstraint i ) { m_sliceSegmentMode = i; } Void setSliceSegmentArgument ( Int i ) { m_sliceSegmentArgument = i; } SliceConstraint getSliceSegmentMode () const { return m_sliceSegmentMode; } Int getSliceSegmentArgument () { return m_sliceSegmentArgument;} Void setLFCrossSliceBoundaryFlag ( Bool bValue ) { m_bLFCrossSliceBoundaryFlag = bValue; } Bool getLFCrossSliceBoundaryFlag () { return m_bLFCrossSliceBoundaryFlag; } Void setUseSAO (Bool bVal) { m_bUseSAO = bVal; } Bool getUseSAO () { return m_bUseSAO; } Void setTestSAODisableAtPictureLevel (Bool bVal) { m_bTestSAODisableAtPictureLevel = bVal; } Bool getTestSAODisableAtPictureLevel ( ) const { return m_bTestSAODisableAtPictureLevel; } Void setSaoEncodingRate(Double v) { m_saoEncodingRate = v; } Double getSaoEncodingRate() const { return m_saoEncodingRate; } Void setSaoEncodingRateChroma(Double v) { m_saoEncodingRateChroma = v; } Double getSaoEncodingRateChroma() const { return m_saoEncodingRateChroma; } Void setMaxNumOffsetsPerPic (Int iVal) { m_maxNumOffsetsPerPic = iVal; } Int getMaxNumOffsetsPerPic () { return m_maxNumOffsetsPerPic; } Void setSaoCtuBoundary (Bool val) { m_saoCtuBoundary = val; } Bool getSaoCtuBoundary () { return m_saoCtuBoundary; } Void setResetEncoderStateAfterIRAP(Bool b) { m_resetEncoderStateAfterIRAP = b; } Bool getResetEncoderStateAfterIRAP() const { return m_resetEncoderStateAfterIRAP; } Void setLFCrossTileBoundaryFlag ( Bool val ) { m_loopFilterAcrossTilesEnabledFlag = val; } Bool getLFCrossTileBoundaryFlag () { return m_loopFilterAcrossTilesEnabledFlag; } Void setTileUniformSpacingFlag ( Bool b ) { m_tileUniformSpacingFlag = b; } Bool getTileUniformSpacingFlag () { return m_tileUniformSpacingFlag; } Void setNumColumnsMinus1 ( Int i ) { m_iNumColumnsMinus1 = i; } Int getNumColumnsMinus1 () { return m_iNumColumnsMinus1; } Void setColumnWidth ( const std::vector& columnWidth ) { m_tileColumnWidth = columnWidth; } UInt getColumnWidth ( UInt columnIdx ) { return m_tileColumnWidth[columnIdx]; } Void setNumRowsMinus1 ( Int i ) { m_iNumRowsMinus1 = i; } Int getNumRowsMinus1 () { return m_iNumRowsMinus1; } Void setRowHeight ( const std::vector& rowHeight) { m_tileRowHeight = rowHeight; } UInt getRowHeight ( UInt rowIdx ) { return m_tileRowHeight[rowIdx]; } Void xCheckGSParameters(); Void setEntropyCodingSyncEnabledFlag(Bool b) { m_entropyCodingSyncEnabledFlag = b; } Bool getEntropyCodingSyncEnabledFlag() const { return m_entropyCodingSyncEnabledFlag; } Void setDecodedPictureHashSEIType(HashType m) { m_decodedPictureHashSEIType = m; } HashType getDecodedPictureHashSEIType() const { return m_decodedPictureHashSEIType; } Void setBufferingPeriodSEIEnabled(Bool b) { m_bufferingPeriodSEIEnabled = b; } Bool getBufferingPeriodSEIEnabled() const { return m_bufferingPeriodSEIEnabled; } Void setPictureTimingSEIEnabled(Bool b) { m_pictureTimingSEIEnabled = b; } Bool getPictureTimingSEIEnabled() const { return m_pictureTimingSEIEnabled; } Void setRecoveryPointSEIEnabled(Bool b) { m_recoveryPointSEIEnabled = b; } Bool getRecoveryPointSEIEnabled() const { return m_recoveryPointSEIEnabled; } Void setToneMappingInfoSEIEnabled(Bool b) { m_toneMappingInfoSEIEnabled = b; } Bool getToneMappingInfoSEIEnabled() { return m_toneMappingInfoSEIEnabled; } Void setTMISEIToneMapId(Int b) { m_toneMapId = b; } Int getTMISEIToneMapId() { return m_toneMapId; } Void setTMISEIToneMapCancelFlag(Bool b) { m_toneMapCancelFlag=b; } Bool getTMISEIToneMapCancelFlag() { return m_toneMapCancelFlag; } Void setTMISEIToneMapPersistenceFlag(Bool b) { m_toneMapPersistenceFlag = b; } Bool getTMISEIToneMapPersistenceFlag() { return m_toneMapPersistenceFlag; } Void setTMISEICodedDataBitDepth(Int b) { m_codedDataBitDepth = b; } Int getTMISEICodedDataBitDepth() { return m_codedDataBitDepth; } Void setTMISEITargetBitDepth(Int b) { m_targetBitDepth = b; } Int getTMISEITargetBitDepth() { return m_targetBitDepth; } Void setTMISEIModelID(Int b) { m_modelId = b; } Int getTMISEIModelID() { return m_modelId; } Void setTMISEIMinValue(Int b) { m_minValue = b; } Int getTMISEIMinValue() { return m_minValue; } Void setTMISEIMaxValue(Int b) { m_maxValue = b; } Int getTMISEIMaxValue() { return m_maxValue; } Void setTMISEISigmoidMidpoint(Int b) { m_sigmoidMidpoint = b; } Int getTMISEISigmoidMidpoint() { return m_sigmoidMidpoint; } Void setTMISEISigmoidWidth(Int b) { m_sigmoidWidth = b; } Int getTMISEISigmoidWidth() { return m_sigmoidWidth; } Void setTMISEIStartOfCodedInterva( Int* p ) { m_startOfCodedInterval = p; } Int* getTMISEIStartOfCodedInterva() { return m_startOfCodedInterval; } Void setTMISEINumPivots(Int b) { m_numPivots = b; } Int getTMISEINumPivots() { return m_numPivots; } Void setTMISEICodedPivotValue( Int* p ) { m_codedPivotValue = p; } Int* getTMISEICodedPivotValue() { return m_codedPivotValue; } Void setTMISEITargetPivotValue( Int* p ) { m_targetPivotValue = p; } Int* getTMISEITargetPivotValue() { return m_targetPivotValue; } Void setTMISEICameraIsoSpeedIdc(Int b) { m_cameraIsoSpeedIdc = b; } Int getTMISEICameraIsoSpeedIdc() { return m_cameraIsoSpeedIdc; } Void setTMISEICameraIsoSpeedValue(Int b) { m_cameraIsoSpeedValue = b; } Int getTMISEICameraIsoSpeedValue() { return m_cameraIsoSpeedValue; } Void setTMISEIExposureIndexIdc(Int b) { m_exposureIndexIdc = b; } Int getTMISEIExposurIndexIdc() { return m_exposureIndexIdc; } Void setTMISEIExposureIndexValue(Int b) { m_exposureIndexValue = b; } Int getTMISEIExposurIndexValue() { return m_exposureIndexValue; } Void setTMISEIExposureCompensationValueSignFlag(Bool b) { m_exposureCompensationValueSignFlag = b; } Bool getTMISEIExposureCompensationValueSignFlag() { return m_exposureCompensationValueSignFlag; } Void setTMISEIExposureCompensationValueNumerator(Int b) { m_exposureCompensationValueNumerator = b; } Int getTMISEIExposureCompensationValueNumerator() { return m_exposureCompensationValueNumerator; } Void setTMISEIExposureCompensationValueDenomIdc(Int b) { m_exposureCompensationValueDenomIdc =b; } Int getTMISEIExposureCompensationValueDenomIdc() { return m_exposureCompensationValueDenomIdc; } Void setTMISEIRefScreenLuminanceWhite(Int b) { m_refScreenLuminanceWhite = b; } Int getTMISEIRefScreenLuminanceWhite() { return m_refScreenLuminanceWhite; } Void setTMISEIExtendedRangeWhiteLevel(Int b) { m_extendedRangeWhiteLevel = b; } Int getTMISEIExtendedRangeWhiteLevel() { return m_extendedRangeWhiteLevel; } Void setTMISEINominalBlackLevelLumaCodeValue(Int b) { m_nominalBlackLevelLumaCodeValue = b; } Int getTMISEINominalBlackLevelLumaCodeValue() { return m_nominalBlackLevelLumaCodeValue; } Void setTMISEINominalWhiteLevelLumaCodeValue(Int b) { m_nominalWhiteLevelLumaCodeValue = b; } Int getTMISEINominalWhiteLevelLumaCodeValue() { return m_nominalWhiteLevelLumaCodeValue; } Void setTMISEIExtendedWhiteLevelLumaCodeValue(Int b) { m_extendedWhiteLevelLumaCodeValue =b; } Int getTMISEIExtendedWhiteLevelLumaCodeValue() { return m_extendedWhiteLevelLumaCodeValue; } Void setFramePackingArrangementSEIEnabled(Bool b) { m_framePackingSEIEnabled = b; } Bool getFramePackingArrangementSEIEnabled() const { return m_framePackingSEIEnabled; } Void setFramePackingArrangementSEIType(Int b) { m_framePackingSEIType = b; } Int getFramePackingArrangementSEIType() { return m_framePackingSEIType; } Void setFramePackingArrangementSEIId(Int b) { m_framePackingSEIId = b; } Int getFramePackingArrangementSEIId() { return m_framePackingSEIId; } Void setFramePackingArrangementSEIQuincunx(Int b) { m_framePackingSEIQuincunx = b; } Int getFramePackingArrangementSEIQuincunx() { return m_framePackingSEIQuincunx; } Void setFramePackingArrangementSEIInterpretation(Int b) { m_framePackingSEIInterpretation = b; } Int getFramePackingArrangementSEIInterpretation() { return m_framePackingSEIInterpretation; } Void setSegmentedRectFramePackingArrangementSEIEnabled(Bool b) { m_segmentedRectFramePackingSEIEnabled = b; } Bool getSegmentedRectFramePackingArrangementSEIEnabled() const { return m_segmentedRectFramePackingSEIEnabled; } Void setSegmentedRectFramePackingArrangementSEICancel(Int b) { m_segmentedRectFramePackingSEICancel = b; } Int getSegmentedRectFramePackingArrangementSEICancel() { return m_segmentedRectFramePackingSEICancel; } Void setSegmentedRectFramePackingArrangementSEIType(Int b) { m_segmentedRectFramePackingSEIType = b; } Int getSegmentedRectFramePackingArrangementSEIType() { return m_segmentedRectFramePackingSEIType; } Void setSegmentedRectFramePackingArrangementSEIPersistence(Int b) { m_segmentedRectFramePackingSEIPersistence = b; } Int getSegmentedRectFramePackingArrangementSEIPersistence() { return m_segmentedRectFramePackingSEIPersistence; } Void setDisplayOrientationSEIAngle(Int b) { m_displayOrientationSEIAngle = b; } Int getDisplayOrientationSEIAngle() { return m_displayOrientationSEIAngle; } Void setTemporalLevel0IndexSEIEnabled(Bool b) { m_temporalLevel0IndexSEIEnabled = b; } Bool getTemporalLevel0IndexSEIEnabled() const { return m_temporalLevel0IndexSEIEnabled; } Void setGradualDecodingRefreshInfoEnabled(Bool b) { m_gradualDecodingRefreshInfoEnabled = b; } Bool getGradualDecodingRefreshInfoEnabled() const { return m_gradualDecodingRefreshInfoEnabled; } Void setNoDisplaySEITLayer(Int b) { m_noDisplaySEITLayer = b; } Int getNoDisplaySEITLayer() { return m_noDisplaySEITLayer; } Void setDecodingUnitInfoSEIEnabled(Bool b) { m_decodingUnitInfoSEIEnabled = b; } Bool getDecodingUnitInfoSEIEnabled() const { return m_decodingUnitInfoSEIEnabled; } Void setSOPDescriptionSEIEnabled(Bool b) { m_SOPDescriptionSEIEnabled = b; } Bool getSOPDescriptionSEIEnabled() const { return m_SOPDescriptionSEIEnabled; } Void setScalableNestingSEIEnabled(Bool b) { m_scalableNestingSEIEnabled = b; } Bool getScalableNestingSEIEnabled() const { return m_scalableNestingSEIEnabled; } Void setTMCTSSEIEnabled(Bool b) { m_tmctsSEIEnabled = b; } Bool getTMCTSSEIEnabled() { return m_tmctsSEIEnabled; } #if MCTS_ENC_CHECK Void setTMCTSSEITileConstraint(Bool b) { m_tmctsSEITileConstraint = b; } Bool getTMCTSSEITileConstraint() { return m_tmctsSEITileConstraint; } #endif #if MCTS_EXTRACTION Void setTMCTSExtractionSEIEnabled(Bool b) { m_tmctsExtractionSEIEnabled = b; } Bool getTMCTSExtractionSEIEnabled() const { return m_tmctsExtractionSEIEnabled; } #endif Void setTimeCodeSEIEnabled(Bool b) { m_timeCodeSEIEnabled = b; } Bool getTimeCodeSEIEnabled() { return m_timeCodeSEIEnabled; } Void setNumberOfTimeSets(Int value) { m_timeCodeSEINumTs = value; } Int getNumberOfTimesets() { return m_timeCodeSEINumTs; } Void setTimeSet(TComSEITimeSet element, Int index) { m_timeSetArray[index] = element; } TComSEITimeSet &getTimeSet(Int index) { return m_timeSetArray[index]; } const TComSEITimeSet &getTimeSet(Int index) const { return m_timeSetArray[index]; } Void setKneeSEIEnabled(Int b) { m_kneeSEIEnabled = b; } Bool getKneeSEIEnabled() { return m_kneeSEIEnabled; } Void setKneeFunctionInformationSEI(const TEncSEIKneeFunctionInformation &seiknee) { m_kneeFunctionInformationSEI = seiknee; } const TEncSEIKneeFunctionInformation &getKneeFunctionInformationSEI() const { return m_kneeFunctionInformationSEI; } Void setCcvSEIEnabled(Bool b) { m_ccvSEIEnabled = b; } Bool getCcvSEIEnabled() { return m_ccvSEIEnabled; } Void setCcvSEICancelFlag(Bool b) { m_ccvSEICancelFlag = b; } Bool getCcvSEICancelFlag() { return m_ccvSEICancelFlag; } Void setCcvSEIPersistenceFlag(Bool b) { m_ccvSEIPersistenceFlag = b; } Bool getCcvSEIPersistenceFlag() { return m_ccvSEIPersistenceFlag; } Void setCcvSEIPrimariesPresentFlag(Bool b) { m_ccvSEIPrimariesPresentFlag = b; } Bool getCcvSEIPrimariesPresentFlag() { return m_ccvSEIPrimariesPresentFlag; } Void setCcvSEIMinLuminanceValuePresentFlag(Bool b) { m_ccvSEIMinLuminanceValuePresentFlag = b; } Bool getCcvSEIMinLuminanceValuePresentFlag() { return m_ccvSEIMinLuminanceValuePresentFlag; } Void setCcvSEIMaxLuminanceValuePresentFlag(Bool b) { m_ccvSEIMaxLuminanceValuePresentFlag = b; } Bool getCcvSEIMaxLuminanceValuePresentFlag() { return m_ccvSEIMaxLuminanceValuePresentFlag; } Void setCcvSEIAvgLuminanceValuePresentFlag(Bool b) { m_ccvSEIAvgLuminanceValuePresentFlag = b; } Bool getCcvSEIAvgLuminanceValuePresentFlag() { return m_ccvSEIAvgLuminanceValuePresentFlag; } Void setCcvSEIPrimariesX(Double dValue, Int index) { m_ccvSEIPrimariesX[index] = dValue; } Double getCcvSEIPrimariesX(Int index) { return m_ccvSEIPrimariesX[index]; } Void setCcvSEIPrimariesY(Double dValue, Int index) { m_ccvSEIPrimariesY[index] = dValue; } Double getCcvSEIPrimariesY(Int index) { return m_ccvSEIPrimariesY[index]; } Void setCcvSEIMinLuminanceValue (Double dValue) { m_ccvSEIMinLuminanceValue = dValue; } Double getCcvSEIMinLuminanceValue () { return m_ccvSEIMinLuminanceValue; } Void setCcvSEIMaxLuminanceValue (Double dValue) { m_ccvSEIMaxLuminanceValue = dValue; } Double getCcvSEIMaxLuminanceValue () { return m_ccvSEIMaxLuminanceValue; } Void setCcvSEIAvgLuminanceValue (Double dValue) { m_ccvSEIAvgLuminanceValue = dValue; } Double getCcvSEIAvgLuminanceValue () { return m_ccvSEIAvgLuminanceValue; } #if SHUTTER_INTERVAL_SEI_MESSAGE Void setSiiSEIEnabled(Bool b) { m_siiSEIEnabled = b; } Bool getSiiSEIEnabled() { return m_siiSEIEnabled; } Void setSiiSEINumUnitsInShutterInterval(UInt value) { m_siiSEINumUnitsInShutterInterval = value; } UInt getSiiSEINumUnitsInShutterInterval() { return m_siiSEINumUnitsInShutterInterval; } Void setSiiSEITimeScale(UInt value) { m_siiSEITimeScale = value; } UInt getSiiSEITimeScale() { return m_siiSEITimeScale; } UInt getSiiSEIMaxSubLayersMinus1() { return UInt(std::max(1u, UInt(m_siiSEISubLayerNumUnitsInSI.size()))-1 ); } Bool getSiiSEIFixedSIwithinCLVS() { return m_siiSEISubLayerNumUnitsInSI.empty(); } Void setSiiSEISubLayerNumUnitsInSI(const std::vector& b) { m_siiSEISubLayerNumUnitsInSI = b; } UInt getSiiSEISubLayerNumUnitsInSI(UInt idx) const { return m_siiSEISubLayerNumUnitsInSI[idx]; } #endif #if SEI_ENCODER_CONTROL // film grain SEI Void setFilmGrainCharactersticsSEIEnabled (Bool b) { m_fgcSEIEnabled = b; } Bool getFilmGrainCharactersticsSEIEnabled() { return m_fgcSEIEnabled; } Void setFilmGrainCharactersticsSEICancelFlag(Bool b) { m_fgcSEICancelFlag = b; } Bool getFilmGrainCharactersticsSEICancelFlag() { return m_fgcSEICancelFlag; } Void setFilmGrainCharactersticsSEIPersistenceFlag(Bool b) { m_fgcSEIPersistenceFlag = b; } Bool getFilmGrainCharactersticsSEIPersistenceFlag() { return m_fgcSEIPersistenceFlag; } Void setFilmGrainCharactersticsSEIModelID(UChar v ) { m_fgcSEIModelID = v; } UChar getFilmGrainCharactersticsSEIModelID() { return m_fgcSEIModelID; } Void setFilmGrainCharactersticsSEISepColourDescPresent(Bool b) { m_fgcSEISepColourDescPresentFlag = b; } Bool getFilmGrainCharactersticsSEISepColourDescPresent() { return m_fgcSEISepColourDescPresentFlag; } Void setFilmGrainCharactersticsSEIBlendingModeID(UChar v ) { m_fgcSEIBlendingModeID = v; } UChar getFilmGrainCharactersticsSEIBlendingModeID() { return m_fgcSEIBlendingModeID; } Void setFilmGrainCharactersticsSEILog2ScaleFactor(UChar v ) { m_fgcSEILog2ScaleFactor = v; } UChar getFilmGrainCharactersticsSEILog2ScaleFactor() { return m_fgcSEILog2ScaleFactor; } Void setFGCSEICompModelPresent(Bool b, Int index) { m_fgcSEICompModelPresent[index] = b; } Bool getFGCSEICompModelPresent(Int index) { return m_fgcSEICompModelPresent[index]; } #if JVET_X0048_X0103_FILM_GRAIN bool* getFGCSEICompModelPresent () { return m_fgcSEICompModelPresent; } void setFilmGrainAnalysisEnabled (bool b) { m_fgcSEIAnalysisEnabled = b; } bool getFilmGrainAnalysisEnabled () { return m_fgcSEIAnalysisEnabled; } void setFilmGrainExternalMask(std::string s) { m_fgcSEIExternalMask = s; } void setFilmGrainExternalDenoised(std::string s) { m_fgcSEIExternalDenoised = s; } std::string getFilmGrainExternalMask() { return m_fgcSEIExternalMask; } std::string getFilmGrainExternalDenoised() { return m_fgcSEIExternalDenoised; } void setFilmGrainCharactersticsSEIPerPictureSEI(bool b) { m_fgcSEIPerPictureSEI = b; } bool getFilmGrainCharactersticsSEIPerPictureSEI() { return m_fgcSEIPerPictureSEI; } Void setFGCSEINumIntensityIntervalMinus1(UChar v, Int index) { m_fgcSEINumIntensityIntervalMinus1[index] = v; } UChar getFGCSEINumIntensityIntervalMinus1(Int index) { return m_fgcSEINumIntensityIntervalMinus1[index]; } Void setFGCSEINumModelValuesMinus1(UChar v, Int index) { m_fgcSEINumModelValuesMinus1[index] = v; } UChar getFGCSEINumModelValuesMinus1(Int index) { return m_fgcSEINumModelValuesMinus1[index]; } Void setFGCSEIIntensityIntervalLowerBound(UChar v, Int index, Int ctr) { m_fgcSEIIntensityIntervalLowerBound[index][ctr] = v; } UChar getFGCSEIIntensityIntervalLowerBound(Int index, Int ctr) { return m_fgcSEIIntensityIntervalLowerBound[index][ctr]; } Void setFGCSEIIntensityIntervalUpperBound(UChar v, Int index, Int ctr) { m_fgcSEIIntensityIntervalUpperBound[index][ctr] = v; } UChar getFGCSEIIntensityIntervalUpperBound(Int index, Int ctr) { return m_fgcSEIIntensityIntervalUpperBound[index][ctr]; } Void setFGCSEICompModelValue(UInt v, Int index, Int ctr, Int modelCtr) { m_fgcSEICompModelValue[index][ctr][modelCtr] = v; } UInt getFGCSEICompModelValue(Int index, Int ctr, Int modelCtr) { return m_fgcSEICompModelValue[index][ctr][modelCtr]; } #endif // cll SEI Void setCLLSEIEnabled(Bool b) { m_cllSEIEnabled = b; } Bool getCLLSEIEnabled() { return m_cllSEIEnabled; } Void setCLLSEIMaxContentLightLevel (UShort v) { m_cllSEIMaxContentLevel = v; } UShort getCLLSEIMaxContentLightLevel() { return m_cllSEIMaxContentLevel; } Void setCLLSEIMaxPicAvgLightLevel(UShort v) { m_cllSEIMaxPicAvgLevel = v; } UShort getCLLSEIMaxPicAvgLightLevel() { return m_cllSEIMaxPicAvgLevel; } // ave SEI Void setAmbientViewingEnvironmentSEIEnabled (Bool b) { m_aveSEIEnabled = b; } Bool getAmbientViewingEnvironmentSEIEnabled () { return m_aveSEIEnabled; } Void setAmbientViewingEnvironmentSEIIlluminance(UInt v ) { m_aveSEIAmbientIlluminance = v; } UInt getAmbientViewingEnvironmentSEIIlluminance() { return m_aveSEIAmbientIlluminance; } Void setAmbientViewingEnvironmentSEIAmbientLightX(UShort v ) { m_aveSEIAmbientLightX = v; } UShort getAmbientViewingEnvironmentSEIAmbientLightX() { return m_aveSEIAmbientLightX; } Void setAmbientViewingEnvironmentSEIAmbientLightY(UShort v ) { m_aveSEIAmbientLightY = v; } UShort getAmbientViewingEnvironmentSEIAmbientLightY() { return m_aveSEIAmbientLightY; } #endif Void setErpSEIEnabled(Bool b) { m_erpSEIEnabled = b; } Bool getErpSEIEnabled() { return m_erpSEIEnabled; } Void setErpSEICancelFlag(Bool b) { m_erpSEICancelFlag = b; } Bool getErpSEICancelFlag() { return m_erpSEICancelFlag; } Void setErpSEIPersistenceFlag(Bool b) { m_erpSEIPersistenceFlag = b; } Bool getErpSEIPersistenceFlag() { return m_erpSEIPersistenceFlag; } Void setErpSEIGuardBandFlag(Bool b) { m_erpSEIGuardBandFlag = b; } Bool getErpSEIGuardBandFlag() { return m_erpSEIGuardBandFlag; } Void setErpSEIGuardBandType(UInt b) { m_erpSEIGuardBandType = b; } UInt getErpSEIGuardBandType() { return m_erpSEIGuardBandType; } Void setErpSEILeftGuardBandWidth(UInt b) { m_erpSEILeftGuardBandWidth = b; } UInt getErpSEILeftGuardBandWidth() { return m_erpSEILeftGuardBandWidth; } Void setErpSEIRightGuardBandWidth(UInt b) { m_erpSEIRightGuardBandWidth = b; } UInt getErpSEIRightGuardBandWidth() { return m_erpSEIRightGuardBandWidth; } Void setSphereRotationSEIEnabled(Bool b) { m_sphereRotationSEIEnabled = b; } Bool getSphereRotationSEIEnabled() { return m_sphereRotationSEIEnabled; } Void setSphereRotationSEICancelFlag(Bool b) { m_sphereRotationSEICancelFlag = b; } Bool getSphereRotationSEICancelFlag() { return m_sphereRotationSEICancelFlag; } Void setSphereRotationSEIPersistenceFlag(Bool b) { m_sphereRotationSEIPersistenceFlag = b; } Bool getSphereRotationSEIPersistenceFlag() { return m_sphereRotationSEIPersistenceFlag; } Void setSphereRotationSEIYaw(Int b) { m_sphereRotationSEIYaw = b; } Int getSphereRotationSEIYaw() { return m_sphereRotationSEIYaw; } Void setSphereRotationSEIPitch(Int b) { m_sphereRotationSEIPitch = b; } Int getSphereRotationSEIPitch() { return m_sphereRotationSEIPitch; } Void setSphereRotationSEIRoll(Int b) { m_sphereRotationSEIRoll = b; } Int getSphereRotationSEIRoll() { return m_sphereRotationSEIRoll; } Void setOmniViewportSEIEnabled(Bool b) { m_omniViewportSEIEnabled = b; } Bool getOmniViewportSEIEnabled() { return m_omniViewportSEIEnabled; } Void setOmniViewportSEIId(UInt b) { m_omniViewportSEIId = b; } UInt getOmniViewportSEIId() { return m_omniViewportSEIId; } Void setOmniViewportSEICancelFlag(Bool b) { m_omniViewportSEICancelFlag = b; } Bool getOmniViewportSEICancelFlag() { return m_omniViewportSEICancelFlag; } Void setOmniViewportSEIPersistenceFlag(Bool b) { m_omniViewportSEIPersistenceFlag = b; } Bool getOmniViewportSEIPersistenceFlag() { return m_omniViewportSEIPersistenceFlag; } Void setOmniViewportSEICntMinus1(UInt b) { m_omniViewportSEICntMinus1 = b; } UInt getOmniViewportSEICntMinus1() { return m_omniViewportSEICntMinus1; } Void setOmniViewportSEIAzimuthCentre(const std::vector& vi) { m_omniViewportSEIAzimuthCentre = vi; } Int getOmniViewportSEIAzimuthCentre(Int idx) { return m_omniViewportSEIAzimuthCentre[idx]; } Void setOmniViewportSEIElevationCentre(const std::vector& vi){ m_omniViewportSEIElevationCentre = vi; } Int getOmniViewportSEIElevationCentre(Int idx) { return m_omniViewportSEIElevationCentre[idx]; } Void setOmniViewportSEITiltCentre(const std::vector& vi) { m_omniViewportSEITiltCentre = vi; } Int getOmniViewportSEITiltCentre(Int idx) { return m_omniViewportSEITiltCentre[idx]; } Void setOmniViewportSEIHorRange(const std::vector& vi) { m_omniViewportSEIHorRange = vi; } UInt getOmniViewportSEIHorRange(Int idx) { return m_omniViewportSEIHorRange[idx]; } Void setOmniViewportSEIVerRange(const std::vector& vi) { m_omniViewportSEIVerRange = vi; } UInt getOmniViewportSEIVerRange(Int idx) { return m_omniViewportSEIVerRange[idx]; } Void setGopBasedTemporalFilterEnabled(Bool flag) { m_gopBasedTemporalFilterEnabled = flag; } Bool getGopBasedTemporalFilterEnabled() const { return m_gopBasedTemporalFilterEnabled; } #if JVET_Y0077_BIM void setBIM(Bool flag) { m_bimEnabled = flag; } Bool getBIM() const { return m_bimEnabled; } void setAdaptQPmap(std::map map) { m_adaptQPmap = map; } Int* getAdaptQPmap(Int poc) { return m_adaptQPmap[poc]; } std::map *getAdaptQPmap() { return &m_adaptQPmap; } #endif Void setCmpSEIEnabled(Bool b) { m_cmpSEIEnabled = b; } Bool getCmpSEIEnabled() { return m_cmpSEIEnabled; } Void setCmpSEICmpCancelFlag(Bool b) { m_cmpSEICmpCancelFlag = b; } Bool getCmpSEICmpCancelFlag() { return m_cmpSEICmpCancelFlag; } Void setCmpSEICmpPersistenceFlag(Bool b) { m_cmpSEICmpPersistenceFlag = b; } Bool getCmpSEICmpPersistenceFlag() { return m_cmpSEICmpPersistenceFlag; } Void setRwpSEIEnabled(Bool b) { m_rwpSEIEnabled = b; } Bool getRwpSEIEnabled() { return m_rwpSEIEnabled; } Void setRwpSEIRwpCancelFlag(Bool b) { m_rwpSEIRwpCancelFlag = b; } Bool getRwpSEIRwpCancelFlag() { return m_rwpSEIRwpCancelFlag; } Void setRwpSEIRwpPersistenceFlag (Bool b) { m_rwpSEIRwpPersistenceFlag = b; } Bool getRwpSEIRwpPersistenceFlag () { return m_rwpSEIRwpPersistenceFlag; } Void setRwpSEIConstituentPictureMatchingFlag (Bool b) { m_rwpSEIConstituentPictureMatchingFlag = b; } Bool getRwpSEIConstituentPictureMatchingFlag () { return m_rwpSEIConstituentPictureMatchingFlag; } Void setRwpSEINumPackedRegions (Int value) { m_rwpSEINumPackedRegions = value; } Int getRwpSEINumPackedRegions () { return m_rwpSEINumPackedRegions; } Void setRwpSEIProjPictureWidth (Int value) { m_rwpSEIProjPictureWidth = value; } Int getRwpSEIProjPictureWidth () { return m_rwpSEIProjPictureWidth; } Void setRwpSEIProjPictureHeight (Int value) { m_rwpSEIProjPictureHeight = value; } Int getRwpSEIProjPictureHeight () { return m_rwpSEIProjPictureHeight; } Void setRwpSEIPackedPictureWidth (Int value) { m_rwpSEIPackedPictureWidth = value; } Int getRwpSEIPackedPictureWidth () { return m_rwpSEIPackedPictureWidth; } Void setRwpSEIPackedPictureHeight (Int value) { m_rwpSEIPackedPictureHeight = value; } Int getRwpSEIPackedPictureHeight () { return m_rwpSEIPackedPictureHeight; } Void setRwpSEIRwpTransformType(const std::vector& rwpTransformType) { m_rwpSEIRwpTransformType =rwpTransformType; } UChar getRwpSEIRwpTransformType(UInt idx) const { return m_rwpSEIRwpTransformType[idx]; } Void setRwpSEIRwpGuardBandFlag(const std::vector& rwpGuardBandFlag) { m_rwpSEIRwpGuardBandFlag = rwpGuardBandFlag; } Bool getRwpSEIRwpGuardBandFlag(UInt idx) const { return m_rwpSEIRwpGuardBandFlag[idx]; } Void setRwpSEIProjRegionWidth(const std::vector& projRegionWidth) { m_rwpSEIProjRegionWidth = projRegionWidth; } UInt getRwpSEIProjRegionWidth(UInt idx) const { return m_rwpSEIProjRegionWidth[idx]; } Void setRwpSEIProjRegionHeight(const std::vector& projRegionHeight) { m_rwpSEIProjRegionHeight = projRegionHeight; } UInt getRwpSEIProjRegionHeight(UInt idx) const { return m_rwpSEIProjRegionHeight[idx]; } Void setRwpSEIRwpSEIProjRegionTop(const std::vector& projRegionTop) { m_rwpSEIRwpSEIProjRegionTop = projRegionTop; } UInt getRwpSEIRwpSEIProjRegionTop(UInt idx) const { return m_rwpSEIRwpSEIProjRegionTop[idx]; } Void setRwpSEIProjRegionLeft(const std::vector& projRegionLeft) { m_rwpSEIProjRegionLeft = projRegionLeft; } UInt getRwpSEIProjRegionLeft(UInt idx) const { return m_rwpSEIProjRegionLeft[idx]; } Void setRwpSEIPackedRegionWidth(const std::vector& packedRegionWidth) { m_rwpSEIPackedRegionWidth = packedRegionWidth; } UShort getRwpSEIPackedRegionWidth(UInt idx) const { return m_rwpSEIPackedRegionWidth[idx]; } Void setRwpSEIPackedRegionHeight(const std::vector& packedRegionHeight) { m_rwpSEIPackedRegionHeight = packedRegionHeight; } UShort getRwpSEIPackedRegionHeight(UInt idx) const { return m_rwpSEIPackedRegionHeight[idx]; } Void setRwpSEIPackedRegionTop(const std::vector& packedRegionTop) { m_rwpSEIPackedRegionTop = packedRegionTop; } UShort getRwpSEIPackedRegionTop(UInt idx) const { return m_rwpSEIPackedRegionTop[idx]; } Void setRwpSEIPackedRegionLeft(const std::vector& packedRegionLeft) { m_rwpSEIPackedRegionLeft = packedRegionLeft; } UShort getRwpSEIPackedRegionLeft(UInt idx) const { return m_rwpSEIPackedRegionLeft[idx]; } Void setRwpSEIRwpLeftGuardBandWidth(const std::vector& rwpLeftGuardBandWidth) { m_rwpSEIRwpLeftGuardBandWidth = rwpLeftGuardBandWidth; } UChar getRwpSEIRwpLeftGuardBandWidth(UInt idx) const { return m_rwpSEIRwpLeftGuardBandWidth[idx]; } Void setRwpSEIRwpRightGuardBandWidth(const std::vector& rwpRightGuardBandWidth) { m_rwpSEIRwpRightGuardBandWidth = rwpRightGuardBandWidth; } UChar getRwpSEIRwpRightGuardBandWidth(UInt idx) const { return m_rwpSEIRwpRightGuardBandWidth[idx]; } Void setRwpSEIRwpTopGuardBandHeight(const std::vector& rwpTopGuardBandHeight) { m_rwpSEIRwpTopGuardBandHeight = rwpTopGuardBandHeight; } UChar getRwpSEIRwpTopGuardBandHeight(UInt idx) const { return m_rwpSEIRwpTopGuardBandHeight[idx]; } Void setRwpSEIRwpBottomGuardBandHeight(const std::vector& rwpBottomGuardBandHeight) { m_rwpSEIRwpBottomGuardBandHeight = rwpBottomGuardBandHeight; } UChar getRwpSEIRwpBottomGuardBandHeight(UInt idx) const { return m_rwpSEIRwpBottomGuardBandHeight[idx]; } Void setRwpSEIRwpGuardBandNotUsedForPredFlag(const std::vector& rwpGuardBandNotUsedForPredFlag){ m_rwpSEIRwpGuardBandNotUsedForPredFlag = rwpGuardBandNotUsedForPredFlag; } Bool getRwpSEIRwpGuardBandNotUsedForPredFlag(UInt idx) const { return m_rwpSEIRwpGuardBandNotUsedForPredFlag[idx]; } Void setRwpSEIRwpGuardBandType(const std::vector& rwpGuardBandType) { m_rwpSEIRwpGuardBandType = rwpGuardBandType; } UChar getRwpSEIRwpGuardBandType(UInt idx) const { return m_rwpSEIRwpGuardBandType[idx]; } Void setFviSEIDisabled() { m_fviSEIEnabled = false; } Void setFviSEIEnabled(const TComSEIFisheyeVideoInfo& fvi) { m_fisheyeVideoInfo=fvi; m_fviSEIEnabled=true; } Bool getFviSEIEnabled() const { return m_fviSEIEnabled; } const TComSEIFisheyeVideoInfo& getFviSEIData() const { return m_fisheyeVideoInfo; } Void setColourRemapInfoSEIFileRoot( const std::string &s ) { m_colourRemapSEIFileRoot = s; } const std::string &getColourRemapInfoSEIFileRoot() const { return m_colourRemapSEIFileRoot; } Void setMasteringDisplaySEI(const TComSEIMasteringDisplay &src) { m_masteringDisplay = src; } Void setSEIAlternativeTransferCharacteristicsSEIEnable( Bool b) { m_alternativeTransferCharacteristicsSEIEnabled = b; } Bool getSEIAlternativeTransferCharacteristicsSEIEnable( ) const { return m_alternativeTransferCharacteristicsSEIEnabled; } Void setSEIPreferredTransferCharacteristics(UChar v) { m_preferredTransferCharacteristics = v; } UChar getSEIPreferredTransferCharacteristics() const { return m_preferredTransferCharacteristics; } Void setSEIGreenMetadataInfoSEIEnable( Bool b) { m_greenMetadataInfoSEIEnabled = b; } Bool getSEIGreenMetadataInfoSEIEnable( ) const { return m_greenMetadataInfoSEIEnabled; } Void setSEIGreenMetadataType(UChar v) { m_greenMetadataType = v; } UChar getSEIGreenMetadataType() const { return m_greenMetadataType; } Void setSEIXSDMetricType(UChar v) { m_xsdMetricType = v; } UChar getSEIXSDMetricType() const { return m_xsdMetricType; } Void setRegionalNestingSEIFileRoot( const std::string &s ) { m_regionalNestingSEIFileRoot = s; } const std::string &getRegionalNestingSEIFileRoot() const { return m_regionalNestingSEIFileRoot; } #if JVET_T0050_ANNOTATED_REGIONS_SEI Void setAnnotatedRegionSEIFileRoot(const std::string &s) { m_arSEIFileRoot = s; m_arObjects.clear(); } #else Void setAnnotatedRegionSEIFileRoot(const std::string &s) { m_arSEIFileRoot = s; } #endif const std::string &getAnnotatedRegionSEIFileRoot() const { return m_arSEIFileRoot; } const TComSEIMasteringDisplay &getMasteringDisplaySEI() const { return m_masteringDisplay; } Void setUseWP ( Bool b ) { m_useWeightedPred = b; } Void setWPBiPred ( Bool b ) { m_useWeightedBiPred = b; } Bool getUseWP () { return m_useWeightedPred; } Bool getWPBiPred () { return m_useWeightedBiPred; } Void setLog2ParallelMergeLevelMinus2 ( UInt u ) { m_log2ParallelMergeLevelMinus2 = u; } UInt getLog2ParallelMergeLevelMinus2 () { return m_log2ParallelMergeLevelMinus2; } Void setMaxNumMergeCand ( UInt u ) { m_maxNumMergeCand = u; } UInt getMaxNumMergeCand () { return m_maxNumMergeCand; } Void setUseScalingListId ( ScalingListMode u ) { m_useScalingListId = u; } ScalingListMode getUseScalingListId () { return m_useScalingListId; } Void setScalingListFileName ( const std::string &s ) { m_scalingListFileName = s; } const std::string& getScalingListFileName () const { return m_scalingListFileName; } Void setTMVPModeId ( Int u ) { m_TMVPModeId = u; } Int getTMVPModeId () { return m_TMVPModeId; } WeightedPredictionMethod getWeightedPredictionMethod() const { return m_weightedPredictionMethod; } Void setWeightedPredictionMethod( WeightedPredictionMethod m ) { m_weightedPredictionMethod = m; } Void setSignDataHidingEnabledFlag( Bool b ) { m_SignDataHidingEnabledFlag = b; } Bool getSignDataHidingEnabledFlag() { return m_SignDataHidingEnabledFlag; } Bool getUseRateCtrl () { return m_RCEnableRateControl; } Void setUseRateCtrl ( Bool b ) { m_RCEnableRateControl = b; } Int getTargetBitrate () { return m_RCTargetBitrate; } Void setTargetBitrate ( Int bitrate ) { m_RCTargetBitrate = bitrate; } Int getKeepHierBit () { return m_RCKeepHierarchicalBit; } Void setKeepHierBit ( Int i ) { m_RCKeepHierarchicalBit = i; } Bool getLCULevelRC () { return m_RCLCULevelRC; } Void setLCULevelRC ( Bool b ) { m_RCLCULevelRC = b; } Bool getUseLCUSeparateModel () { return m_RCUseLCUSeparateModel; } Void setUseLCUSeparateModel ( Bool b ) { m_RCUseLCUSeparateModel = b; } Int getInitialQP () { return m_RCInitialQP; } Void setInitialQP ( Int QP ) { m_RCInitialQP = QP; } Bool getForceIntraQP () { return m_RCForceIntraQP; } Void setForceIntraQP ( Bool b ) { m_RCForceIntraQP = b; } Bool getCpbSaturationEnabled() { return m_RCCpbSaturationEnabled;} Void setCpbSaturationEnabled( Bool b ) { m_RCCpbSaturationEnabled = b; } UInt getCpbSize () { return m_RCCpbSize;} Void setCpbSize ( UInt ui ) { m_RCCpbSize = ui; } Double getInitialCpbFullness () { return m_RCInitialCpbFullness; } Void setInitialCpbFullness (Double f) { m_RCInitialCpbFullness = f; } Bool getTransquantBypassEnabledFlag() { return m_TransquantBypassEnabledFlag; } Void setTransquantBypassEnabledFlag(Bool flag) { m_TransquantBypassEnabledFlag = flag; } Bool getCUTransquantBypassFlagForceValue() { return m_CUTransquantBypassFlagForce; } Void setCUTransquantBypassFlagForceValue(Bool flag) { m_CUTransquantBypassFlagForce = flag; } CostMode getCostMode( ) const { return m_costMode; } Void setCostMode(CostMode m ) { m_costMode = m; } Void setVPS(TComVPS *p) { m_cVPS = *p; } TComVPS * getVPS() { return &m_cVPS; } Void setUseRecalculateQPAccordingToLambda (Bool b) { m_recalculateQPAccordingToLambda = b; } Bool getUseRecalculateQPAccordingToLambda () { return m_recalculateQPAccordingToLambda; } Void setUseStrongIntraSmoothing ( Bool b ) { m_useStrongIntraSmoothing = b; } Bool getUseStrongIntraSmoothing () { return m_useStrongIntraSmoothing; } Void setEfficientFieldIRAPEnabled( Bool b ) { m_bEfficientFieldIRAPEnabled = b; } Bool getEfficientFieldIRAPEnabled( ) const { return m_bEfficientFieldIRAPEnabled; } Void setHarmonizeGopFirstFieldCoupleEnabled( Bool b ) { m_bHarmonizeGopFirstFieldCoupleEnabled = b; } Bool getHarmonizeGopFirstFieldCoupleEnabled( ) const { return m_bHarmonizeGopFirstFieldCoupleEnabled; } Void setActiveParameterSetsSEIEnabled ( Int b ) { m_activeParameterSetsSEIEnabled = b; } Int getActiveParameterSetsSEIEnabled () { return m_activeParameterSetsSEIEnabled; } Bool getVuiParametersPresentFlag() { return m_vuiParametersPresentFlag; } Void setVuiParametersPresentFlag(Bool i) { m_vuiParametersPresentFlag = i; } Bool getAspectRatioInfoPresentFlag() { return m_aspectRatioInfoPresentFlag; } Void setAspectRatioInfoPresentFlag(Bool i) { m_aspectRatioInfoPresentFlag = i; } Int getAspectRatioIdc() { return m_aspectRatioIdc; } Void setAspectRatioIdc(Int i) { m_aspectRatioIdc = i; } Int getSarWidth() { return m_sarWidth; } Void setSarWidth(Int i) { m_sarWidth = i; } Int getSarHeight() { return m_sarHeight; } Void setSarHeight(Int i) { m_sarHeight = i; } Bool getOverscanInfoPresentFlag() { return m_overscanInfoPresentFlag; } Void setOverscanInfoPresentFlag(Bool i) { m_overscanInfoPresentFlag = i; } Bool getOverscanAppropriateFlag() { return m_overscanAppropriateFlag; } Void setOverscanAppropriateFlag(Bool i) { m_overscanAppropriateFlag = i; } Bool getVideoSignalTypePresentFlag() { return m_videoSignalTypePresentFlag; } Void setVideoSignalTypePresentFlag(Bool i) { m_videoSignalTypePresentFlag = i; } Int getVideoFormat() { return m_videoFormat; } Void setVideoFormat(Int i) { m_videoFormat = i; } Bool getVideoFullRangeFlag() { return m_videoFullRangeFlag; } Void setVideoFullRangeFlag(Bool i) { m_videoFullRangeFlag = i; } Bool getColourDescriptionPresentFlag() { return m_colourDescriptionPresentFlag; } Void setColourDescriptionPresentFlag(Bool i) { m_colourDescriptionPresentFlag = i; } Int getColourPrimaries() { return m_colourPrimaries; } Void setColourPrimaries(Int i) { m_colourPrimaries = i; } Int getTransferCharacteristics() { return m_transferCharacteristics; } Void setTransferCharacteristics(Int i) { m_transferCharacteristics = i; } Int getMatrixCoefficients() { return m_matrixCoefficients; } Void setMatrixCoefficients(Int i) { m_matrixCoefficients = i; } Bool getChromaLocInfoPresentFlag() { return m_chromaLocInfoPresentFlag; } Void setChromaLocInfoPresentFlag(Bool i) { m_chromaLocInfoPresentFlag = i; } Int getChromaSampleLocTypeTopField() { return m_chromaSampleLocTypeTopField; } Void setChromaSampleLocTypeTopField(Int i) { m_chromaSampleLocTypeTopField = i; } Int getChromaSampleLocTypeBottomField() { return m_chromaSampleLocTypeBottomField; } Void setChromaSampleLocTypeBottomField(Int i) { m_chromaSampleLocTypeBottomField = i; } Bool getNeutralChromaIndicationFlag() { return m_neutralChromaIndicationFlag; } Void setNeutralChromaIndicationFlag(Bool i) { m_neutralChromaIndicationFlag = i; } Window &getDefaultDisplayWindow() { return m_defaultDisplayWindow; } Void setDefaultDisplayWindow (Int offsetLeft, Int offsetRight, Int offsetTop, Int offsetBottom ) { m_defaultDisplayWindow.setWindow (offsetLeft, offsetRight, offsetTop, offsetBottom); } Bool getFrameFieldInfoPresentFlag() { return m_frameFieldInfoPresentFlag; } Void setFrameFieldInfoPresentFlag(Bool i) { m_frameFieldInfoPresentFlag = i; } Bool getPocProportionalToTimingFlag() { return m_pocProportionalToTimingFlag; } Void setPocProportionalToTimingFlag(Bool x) { m_pocProportionalToTimingFlag = x; } Int getNumTicksPocDiffOneMinus1() { return m_numTicksPocDiffOneMinus1; } Void setNumTicksPocDiffOneMinus1(Int x) { m_numTicksPocDiffOneMinus1 = x; } Bool getBitstreamRestrictionFlag() { return m_bitstreamRestrictionFlag; } Void setBitstreamRestrictionFlag(Bool i) { m_bitstreamRestrictionFlag = i; } Bool getTilesFixedStructureFlag() { return m_tilesFixedStructureFlag; } Void setTilesFixedStructureFlag(Bool i) { m_tilesFixedStructureFlag = i; } Bool getMotionVectorsOverPicBoundariesFlag() { return m_motionVectorsOverPicBoundariesFlag; } Void setMotionVectorsOverPicBoundariesFlag(Bool i) { m_motionVectorsOverPicBoundariesFlag = i; } Int getMinSpatialSegmentationIdc() { return m_minSpatialSegmentationIdc; } Void setMinSpatialSegmentationIdc(Int i) { m_minSpatialSegmentationIdc = i; } Int getMaxBytesPerPicDenom() { return m_maxBytesPerPicDenom; } Void setMaxBytesPerPicDenom(Int i) { m_maxBytesPerPicDenom = i; } Int getMaxBitsPerMinCuDenom() { return m_maxBitsPerMinCuDenom; } Void setMaxBitsPerMinCuDenom(Int i) { m_maxBitsPerMinCuDenom = i; } Int getLog2MaxMvLengthHorizontal() { return m_log2MaxMvLengthHorizontal; } Void setLog2MaxMvLengthHorizontal(Int i) { m_log2MaxMvLengthHorizontal = i; } Int getLog2MaxMvLengthVertical() { return m_log2MaxMvLengthVertical; } Void setLog2MaxMvLengthVertical(Int i) { m_log2MaxMvLengthVertical = i; } Bool getProgressiveSourceFlag() const { return m_progressiveSourceFlag; } Void setProgressiveSourceFlag(Bool b) { m_progressiveSourceFlag = b; } Bool getInterlacedSourceFlag() const { return m_interlacedSourceFlag; } Void setInterlacedSourceFlag(Bool b) { m_interlacedSourceFlag = b; } Bool getNonPackedConstraintFlag() const { return m_nonPackedConstraintFlag; } Void setNonPackedConstraintFlag(Bool b) { m_nonPackedConstraintFlag = b; } Bool getFrameOnlyConstraintFlag() const { return m_frameOnlyConstraintFlag; } Void setFrameOnlyConstraintFlag(Bool b) { m_frameOnlyConstraintFlag = b; } UInt getBitDepthConstraintValue() const { return m_bitDepthConstraintValue; } Void setBitDepthConstraintValue(UInt v) { m_bitDepthConstraintValue=v; } ChromaFormat getChromaFormatConstraintValue() const { return m_chromaFormatConstraintValue; } Void setChromaFormatConstraintValue(ChromaFormat v) { m_chromaFormatConstraintValue=v; } Bool getIntraConstraintFlag() const { return m_intraConstraintFlag; } Void setIntraConstraintFlag(Bool b) { m_intraConstraintFlag=b; } Bool getOnePictureOnlyConstraintFlag() const { return m_onePictureOnlyConstraintFlag; } Void setOnePictureOnlyConstraintFlag(Bool b) { m_onePictureOnlyConstraintFlag=b; } Bool getLowerBitRateConstraintFlag() const { return m_lowerBitRateConstraintFlag; } Void setLowerBitRateConstraintFlag(Bool b) { m_lowerBitRateConstraintFlag=b; } Bool getChromaResamplingFilterHintEnabled() { return m_chromaResamplingFilterHintEnabled;} Void setChromaResamplingFilterHintEnabled(Bool i) { m_chromaResamplingFilterHintEnabled = i;} Int getChromaResamplingHorFilterIdc() { return m_chromaResamplingHorFilterIdc;} Void setChromaResamplingHorFilterIdc(Int i) { m_chromaResamplingHorFilterIdc = i;} Int getChromaResamplingVerFilterIdc() { return m_chromaResamplingVerFilterIdc;} Void setChromaResamplingVerFilterIdc(Int i) { m_chromaResamplingVerFilterIdc = i;} Void setSummaryOutFilename(const std::string &s) { m_summaryOutFilename = s; } const std::string& getSummaryOutFilename() const { return m_summaryOutFilename; } Void setSummaryPicFilenameBase(const std::string &s) { m_summaryPicFilenameBase = s; } const std::string& getSummaryPicFilenameBase() const { return m_summaryPicFilenameBase; } Void setSummaryVerboseness(UInt v) { m_summaryVerboseness = v; } UInt getSummaryVerboseness( ) const { return m_summaryVerboseness; } #if JCTVC_AD0021_SEI_MANIFEST Void setSEIManifestSEIEnabled(Bool b) { m_SEIManifestSEIEnabled = b; } Bool getSEIManifestSEIEnabled() { return m_SEIManifestSEIEnabled; } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION Void setSEIPrefixIndicationSEIEnabled(Bool b) { m_SEIPrefixIndicationSEIEnabled = b; } Bool getSEIPrefixIndicationSEIEnabled() { return m_SEIPrefixIndicationSEIEnabled; } #endif }; //! \} #endif // !defined(AFX_TENCCFG_H__6B99B797_F4DA_4E46_8E78_7656339A6C41__INCLUDED_) HM-HM-18.0/source/Lib/TLibEncoder/TEncCu.cpp000066400000000000000000002234741442026013100202420ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncCu.cpp \brief Coding Unit (CU) encoder class */ #include #include "TEncTop.h" #include "TEncCu.h" #include "TEncAnalyze.h" #include "TLibCommon/Debug.h" #include #include using namespace std; //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== /** \param uhTotalDepth total number of allowable depth \param uiMaxWidth largest CU width \param uiMaxHeight largest CU height \param chromaFormat chroma format */ Void TEncCu::create(UChar uhTotalDepth, UInt uiMaxWidth, UInt uiMaxHeight, ChromaFormat chromaFormat) { Int i; m_uhTotalDepth = uhTotalDepth + 1; m_ppcBestCU = new TComDataCU*[m_uhTotalDepth-1]; m_ppcTempCU = new TComDataCU*[m_uhTotalDepth-1]; m_ppcPredYuvBest = new TComYuv*[m_uhTotalDepth-1]; m_ppcResiYuvBest = new TComYuv*[m_uhTotalDepth-1]; m_ppcRecoYuvBest = new TComYuv*[m_uhTotalDepth-1]; m_ppcPredYuvTemp = new TComYuv*[m_uhTotalDepth-1]; m_ppcResiYuvTemp = new TComYuv*[m_uhTotalDepth-1]; m_ppcRecoYuvTemp = new TComYuv*[m_uhTotalDepth-1]; m_ppcOrigYuv = new TComYuv*[m_uhTotalDepth-1]; UInt uiNumPartitions; for( i=0 ; i> i; UInt uiHeight = uiMaxHeight >> i; m_ppcBestCU[i] = new TComDataCU; m_ppcBestCU[i]->create( chromaFormat, uiNumPartitions, uiWidth, uiHeight, false, uiMaxWidth >> (m_uhTotalDepth - 1) ); m_ppcTempCU[i] = new TComDataCU; m_ppcTempCU[i]->create( chromaFormat, uiNumPartitions, uiWidth, uiHeight, false, uiMaxWidth >> (m_uhTotalDepth - 1) ); m_ppcPredYuvBest[i] = new TComYuv; m_ppcPredYuvBest[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcResiYuvBest[i] = new TComYuv; m_ppcResiYuvBest[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcRecoYuvBest[i] = new TComYuv; m_ppcRecoYuvBest[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcPredYuvTemp[i] = new TComYuv; m_ppcPredYuvTemp[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcResiYuvTemp[i] = new TComYuv; m_ppcResiYuvTemp[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcRecoYuvTemp[i] = new TComYuv; m_ppcRecoYuvTemp[i]->create(uiWidth, uiHeight, chromaFormat); m_ppcOrigYuv [i] = new TComYuv; m_ppcOrigYuv [i]->create(uiWidth, uiHeight, chromaFormat); } m_bEncodeDQP = false; m_stillToCodeChromaQpOffsetFlag = false; m_cuChromaQpOffsetIdxPlus1 = 0; m_bFastDeltaQP = false; // initialize partition order. UInt* piTmp = &g_auiZscanToRaster[0]; initZscanToRaster( m_uhTotalDepth, 1, 0, piTmp); initRasterToZscan( uiMaxWidth, uiMaxHeight, m_uhTotalDepth ); // initialize conversion matrix from partition index to pel initRasterToPelXY( uiMaxWidth, uiMaxHeight, m_uhTotalDepth ); } Void TEncCu::destroy() { Int i; for( i=0 ; idestroy(); delete m_ppcBestCU[i]; m_ppcBestCU[i] = NULL; } if(m_ppcTempCU[i]) { m_ppcTempCU[i]->destroy(); delete m_ppcTempCU[i]; m_ppcTempCU[i] = NULL; } if(m_ppcPredYuvBest[i]) { m_ppcPredYuvBest[i]->destroy(); delete m_ppcPredYuvBest[i]; m_ppcPredYuvBest[i] = NULL; } if(m_ppcResiYuvBest[i]) { m_ppcResiYuvBest[i]->destroy(); delete m_ppcResiYuvBest[i]; m_ppcResiYuvBest[i] = NULL; } if(m_ppcRecoYuvBest[i]) { m_ppcRecoYuvBest[i]->destroy(); delete m_ppcRecoYuvBest[i]; m_ppcRecoYuvBest[i] = NULL; } if(m_ppcPredYuvTemp[i]) { m_ppcPredYuvTemp[i]->destroy(); delete m_ppcPredYuvTemp[i]; m_ppcPredYuvTemp[i] = NULL; } if(m_ppcResiYuvTemp[i]) { m_ppcResiYuvTemp[i]->destroy(); delete m_ppcResiYuvTemp[i]; m_ppcResiYuvTemp[i] = NULL; } if(m_ppcRecoYuvTemp[i]) { m_ppcRecoYuvTemp[i]->destroy(); delete m_ppcRecoYuvTemp[i]; m_ppcRecoYuvTemp[i] = NULL; } if(m_ppcOrigYuv[i]) { m_ppcOrigYuv[i]->destroy(); delete m_ppcOrigYuv[i]; m_ppcOrigYuv[i] = NULL; } } if(m_ppcBestCU) { delete [] m_ppcBestCU; m_ppcBestCU = NULL; } if(m_ppcTempCU) { delete [] m_ppcTempCU; m_ppcTempCU = NULL; } if(m_ppcPredYuvBest) { delete [] m_ppcPredYuvBest; m_ppcPredYuvBest = NULL; } if(m_ppcResiYuvBest) { delete [] m_ppcResiYuvBest; m_ppcResiYuvBest = NULL; } if(m_ppcRecoYuvBest) { delete [] m_ppcRecoYuvBest; m_ppcRecoYuvBest = NULL; } if(m_ppcPredYuvTemp) { delete [] m_ppcPredYuvTemp; m_ppcPredYuvTemp = NULL; } if(m_ppcResiYuvTemp) { delete [] m_ppcResiYuvTemp; m_ppcResiYuvTemp = NULL; } if(m_ppcRecoYuvTemp) { delete [] m_ppcRecoYuvTemp; m_ppcRecoYuvTemp = NULL; } if(m_ppcOrigYuv) { delete [] m_ppcOrigYuv; m_ppcOrigYuv = NULL; } } /** \param pcEncTop pointer of encoder class */ Void TEncCu::init( TEncTop* pcEncTop ) { m_pcEncCfg = pcEncTop; m_pcPredSearch = pcEncTop->getPredSearch(); m_pcTrQuant = pcEncTop->getTrQuant(); m_pcRdCost = pcEncTop->getRdCost(); m_pcEntropyCoder = pcEncTop->getEntropyCoder(); m_pcBinCABAC = pcEncTop->getBinCABAC(); m_pppcRDSbacCoder = pcEncTop->getRDSbacCoder(); m_pcRDGoOnSbacCoder = pcEncTop->getRDGoOnSbacCoder(); m_pcRateCtrl = pcEncTop->getRateCtrl(); m_lumaQPOffset = 0; initLumaDeltaQpLUT(); #if JVET_V0078 m_smoothQPoffset = 0; #endif #if JVET_Y0077_BIM m_BimQPoffset = 0; #endif } // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** \param pCtu pointer of CU data class */ Void TEncCu::compressCtu( TComDataCU* pCtu ) { // initialize CU data m_ppcBestCU[0]->initCtu( pCtu->getPic(), pCtu->getCtuRsAddr() ); m_ppcTempCU[0]->initCtu( pCtu->getPic(), pCtu->getCtuRsAddr() ); m_bEncodeDQP = false; // analysis of CU DEBUG_STRING_NEW(sDebug) xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 DEBUG_STRING_PASS_INTO(sDebug) ); DEBUG_STRING_OUTPUT(std::cout, sDebug) #if ADAPTIVE_QP_SELECTION if( m_pcEncCfg->getUseAdaptQpSelect() ) { if(pCtu->getSlice()->getSliceType()!=I_SLICE) //IIII { xCtuCollectARLStats( pCtu ); } } #endif } /** \param pCtu pointer of CU data class */ Void TEncCu::encodeCtu ( TComDataCU* pCtu ) { if ( pCtu->getSlice()->getPPS()->getUseDQP() ) { setdQPFlag(true); } if ( pCtu->getSlice()->getUseChromaQpAdj() ) { setCodeChromaQpAdjFlag(true); } // Encode CU data xEncodeCU( pCtu, 0, 0 ); } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Void TEncCu::initLumaDeltaQpLUT() { const LumaLevelToDeltaQPMapping &mapping=m_pcEncCfg->getLumaLevelToDeltaQPMapping(); if ( !mapping.isEnabled() ) { return; } // map the sparse LumaLevelToDeltaQPMapping.mapping to a fully populated linear table. Int lastDeltaQPValue=0; std::size_t nextSparseIndex=0; for(Int index=0; index=mapping.mapping[nextSparseIndex].first) { lastDeltaQPValue=mapping.mapping[nextSparseIndex].second; nextSparseIndex++; } m_lumaLevelToDeltaQPLUT[index]=lastDeltaQPValue; } } Int TEncCu::calculateLumaDQP(TComDataCU *pCU, const UInt absPartIdx, const TComYuv * pOrgYuv) { const Pel *pY = pOrgYuv->getAddr(COMPONENT_Y, absPartIdx); const Int stride = pOrgYuv->getStride(COMPONENT_Y); Int width = pCU->getWidth(absPartIdx); Int height = pCU->getHeight(absPartIdx); Double avg = 0; // limit the block by picture size const TComSPS* pSPS = pCU->getSlice()->getSPS(); if ( pCU->getCUPelX() + width > pSPS->getPicWidthInLumaSamples() ) { width = pSPS->getPicWidthInLumaSamples() - pCU->getCUPelX(); } if ( pCU->getCUPelY() + height > pSPS->getPicHeightInLumaSamples() ) { height = pSPS->getPicHeightInLumaSamples() - pCU->getCUPelY(); } // Get QP offset derived from Luma level if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().mode == LUMALVL_TO_DQP_AVG_METHOD ) { // Use avg method Int sum = 0; for (Int y = 0; y < height; y++) { for (Int x = 0; x < width; x++) { sum += pY[x]; } pY += stride; } avg = (Double)sum/(width*height); } else { // Use maximum luma value Int maxVal = 0; for (Int y = 0; y < height; y++) { for (Int x = 0; x < width; x++) { if (pY[x] > maxVal) { maxVal = pY[x]; } } pY += stride; } // use a percentage of the maxVal avg = (Double)maxVal * m_pcEncCfg->getLumaLevelToDeltaQPMapping().maxMethodWeight; } Int lumaIdx = Clip3(0, Int(LUMA_LEVEL_TO_DQP_LUT_MAXSIZE)-1, Int(avg+0.5) ); Int QP = m_lumaLevelToDeltaQPLUT[lumaIdx]; return QP; } #if JVET_V0078 Int TEncCu::calculateLumaDQPsmooth(TComDataCU *pCU, const UInt absPartIdx, const TComYuv * pOrgYuv, Int iBaseQP) { const Pel *pY = pOrgYuv->getAddr(COMPONENT_Y, absPartIdx); const Int stride = pOrgYuv->getStride(COMPONENT_Y); Double avg = 0; Double diff = 0; Int width = pCU->getWidth(absPartIdx); Int height = pCU->getHeight(absPartIdx); Double thr = (Double)m_pcEncCfg->getSmoothQPReductionThreshold()*height*width; Int iQP = 0; if (height == 64 && width == 64) { Int sum = 0; for (Int y = 0; y < height; y++) { for (Int x = 0; x < width; x++) { sum += pY[x]; } pY += stride; } avg = (Double)sum; // determine parameters for 1+x+y+x*x+y*y model const Int numBasis = 6; Double invb[numBasis][numBasis] = { {0.001*0.244140625000000, 0, 0, 0, 0, 0}, {0, 0.001*0.013204564833946, 0.001*0.002080251479290, -0.001*0.000066039729501, -0.001*0.000165220364313, 0.000000000000000}, {0, 0.001*0.002080251479290, 0.001*0.013204564833946, -0.001*0.000066039729501, 0.000000000000000, -0.001*0.000165220364313}, {0, -0.001*0.000066039729501, -0.001*0.000066039729501, 0.001*0.000002096499349, 0.000000000000000, 0.000000000000000}, {0, -0.001*0.000165220364313, 0.000000000000000, 0.000000000000000, 0.001*0.000002622545465, 0.000000000000000}, {0, 0.000000000000000, -0.001*0.000165220364313, 0.000000000000000, 0.000000000000000, 0.001*0.000002622545465} }; Double boffset[5] = { -31.5, -31.5, -992.25, -1333.5, -1333.5 }; Double b1sum = avg; Double b2sum = 0.0; Double b3sum = 0.0; Double b4sum = 0.0; Double b5sum = 0.0;; Double b6sum = 0.0;; const Pel *pY1 = pOrgYuv->getAddr(COMPONENT_Y, absPartIdx); for (Int y = 0; y < height; y++) { for (Int x = 0; x < width; x++) { b2sum += ((Double)pY1[x])*((Double)x + boffset[0]); b3sum += ((Double)pY1[x])*((Double)y + boffset[1]); b4sum += ((Double)pY1[x])*((Double)x*(Double)y + boffset[2]); b5sum += ((Double)pY1[x])*((Double)x*(Double)x + boffset[3]); b6sum += ((Double)pY1[x])*((Double)y*(Double)y + boffset[4]); } pY1 += stride; } Double r[numBasis]; for (Int b = 0; b < numBasis; b++) { r[b] = invb[b][0] * b1sum + invb[b][1] * b2sum + invb[b][2] * b3sum + invb[b][3] * b4sum + invb[b][4] * b5sum + invb[b][5] * b6sum; } // compute SAD for model const Pel *pY2 = pOrgYuv->getAddr(COMPONENT_Y, absPartIdx); for (Int y = 0; y < height; y++) { for (Int x = 0; x < width; x++) { diff += abs((Int)pY2[x] - (Int)(r[0] + r[1] * ((Double)x + boffset[0]) + r[2] * ((Double)y + boffset[1]) + r[3] * ((Double)x*(Double)y + boffset[2]) + r[4] * ((Double)x*(Double)x + boffset[3]) + r[5] * ((Double)y*(Double)y + boffset[4]))); } pY2 += stride; } if (diff < thr) { iQP = std::max(m_pcEncCfg->getSmoothQPReductionLimit(), std::min(0, (Int)(m_pcEncCfg->getSmoothQPReductionModelScale()*(Double)iBaseQP + m_pcEncCfg->getSmoothQPReductionModelOffset()))); } } return iQP; } #endif //! Derive small set of test modes for AMP encoder speed-up #if AMP_ENC_SPEEDUP #if AMP_MRG Void TEncCu::deriveTestModeAMP (TComDataCU *pcBestCU, PartSize eParentPartSize, Bool &bTestAMP_Hor, Bool &bTestAMP_Ver, Bool &bTestMergeAMP_Hor, Bool &bTestMergeAMP_Ver) #else Void TEncCu::deriveTestModeAMP (TComDataCU *pcBestCU, PartSize eParentPartSize, Bool &bTestAMP_Hor, Bool &bTestAMP_Ver) #endif { if ( pcBestCU->getPartitionSize(0) == SIZE_2NxN ) { bTestAMP_Hor = true; } else if ( pcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { bTestAMP_Ver = true; } else if ( pcBestCU->getPartitionSize(0) == SIZE_2Nx2N && pcBestCU->getMergeFlag(0) == false && pcBestCU->isSkipped(0) == false ) { bTestAMP_Hor = true; bTestAMP_Ver = true; } #if AMP_MRG //! Utilizing the partition size of parent PU if ( eParentPartSize >= SIZE_2NxnU && eParentPartSize <= SIZE_nRx2N ) { bTestMergeAMP_Hor = true; bTestMergeAMP_Ver = true; } if ( eParentPartSize == NUMBER_OF_PART_SIZES ) //! if parent is intra { if ( pcBestCU->getPartitionSize(0) == SIZE_2NxN ) { bTestMergeAMP_Hor = true; } else if ( pcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { bTestMergeAMP_Ver = true; } } if ( pcBestCU->getPartitionSize(0) == SIZE_2Nx2N && pcBestCU->isSkipped(0) == false ) { bTestMergeAMP_Hor = true; bTestMergeAMP_Ver = true; } if ( pcBestCU->getWidth(0) == 64 ) { bTestAMP_Hor = false; bTestAMP_Ver = false; } #else //! Utilizing the partition size of parent PU if ( eParentPartSize >= SIZE_2NxnU && eParentPartSize <= SIZE_nRx2N ) { bTestAMP_Hor = true; bTestAMP_Ver = true; } if ( eParentPartSize == SIZE_2Nx2N ) { bTestAMP_Hor = false; bTestAMP_Ver = false; } #endif } #endif // ==================================================================================================================== // Protected member functions // ==================================================================================================================== /** Compress a CU block recursively with enabling sub-CTU-level delta QP * - for loop of QP value to compress the current CU with all possible QP */ #if AMP_ENC_SPEEDUP Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth DEBUG_STRING_FN_DECLARE(sDebug_), PartSize eParentPartSize ) #else Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth ) #endif { TComPic* pcPic = rpcBestCU->getPic(); DEBUG_STRING_NEW(sDebug) const TComPPS &pps=*(rpcTempCU->getSlice()->getPPS()); const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); // These are only used if getFastDeltaQp() is true const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMaxCUHeight()>>sps.getLog2DiffMaxMinCodingBlockSize(), sps.getMaxCUHeight(), 32u); // get Original YUV data from picture m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu() ); // variable for Cbf fast mode PU decision Bool doNotBlockPu = true; Bool earlyDetectionSkipMode = false; const UInt uiLPelX = rpcBestCU->getCUPelX(); const UInt uiRPelX = uiLPelX + rpcBestCU->getWidth(0) - 1; const UInt uiTPelY = rpcBestCU->getCUPelY(); const UInt uiBPelY = uiTPelY + rpcBestCU->getHeight(0) - 1; const UInt uiWidth = rpcBestCU->getWidth(0); Int iBaseQP = xComputeQP( rpcBestCU, uiDepth ); Int iMinQP; Int iMaxQP; Bool isAddLowestQP = false; const UInt numberValidComponents = rpcBestCU->getPic()->getNumberValidComponents(); if( uiDepth <= pps.getMaxCuDQPDepth() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP+idQP ); } else { iMinQP = rpcTempCU->getQP(0); iMaxQP = rpcTempCU->getQP(0); } if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() ) { if ( uiDepth <= pps.getMaxCuDQPDepth() ) { // keep using the same m_QP_LUMA_OFFSET in the same CTU m_lumaQPOffset = calculateLumaDQP(rpcTempCU, 0, m_ppcOrigYuv[uiDepth]); } iMinQP = Clip3(-sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP - m_lumaQPOffset); iMaxQP = iMinQP; // force encode choose the modified QO } #if JVET_V0078 if (m_pcEncCfg->getSmoothQPReductionEnable()) { if (uiDepth <= pps.getMaxCuDQPDepth()) { m_smoothQPoffset = 0; // enable smooth QP reduction on selected frames bool checkSmoothQP = false; if (m_pcEncCfg->getSmoothQPReductionPeriodicity() != 0) { checkSmoothQP = ((m_pcEncCfg->getSmoothQPReductionPeriodicity() == 0) && rpcTempCU->getSlice()->isIntra()) || (m_pcEncCfg->getSmoothQPReductionPeriodicity() == 1) || ((rpcTempCU->getSlice()->getPOC() % m_pcEncCfg->getSmoothQPReductionPeriodicity()) == 0); } else { checkSmoothQP = ((m_pcEncCfg->getSmoothQPReductionPeriodicity() == 0) && rpcTempCU->getSlice()->isIntra()); } if (checkSmoothQP) { if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) { m_smoothQPoffset = calculateLumaDQPsmooth(rpcTempCU, 0, m_ppcOrigYuv[uiDepth], iBaseQP - m_lumaQPOffset); } else { m_smoothQPoffset = calculateLumaDQPsmooth(rpcTempCU, 0, m_ppcOrigYuv[uiDepth], iBaseQP); } } } if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()) { iMinQP = Clip3(-sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP - m_lumaQPOffset + m_smoothQPoffset); } else { iMinQP = Clip3(-sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP + m_smoothQPoffset); } iMaxQP = iMinQP; // force encode choose the modified QO } #endif #if JVET_Y0077_BIM if( m_pcEncCfg->getBIM() ) { if ( uiDepth <= pps.getMaxCuDQPDepth() ) { std::map *QPmap = m_pcEncCfg->getAdaptQPmap(); Int iCTUoffset = uiTPelY / MAX_CU_SIZE * pcPic->getFrameWidthInCtus() + uiLPelX / MAX_CU_SIZE; m_BimQPoffset = ( QPmap->find( pcPic->getPOC() ) == QPmap->end() ) ? 0 : (*QPmap)[pcPic->getPOC()][iCTUoffset]; } Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP - idQP - m_lumaQPOffset + m_smoothQPoffset + m_BimQPoffset ); iMaxQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP + idQP - m_lumaQPOffset + m_smoothQPoffset + m_BimQPoffset ); } #endif if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } // transquant-bypass (TQB) processing loop variable initialisation --- const Int lowestQP = iMinQP; // For TQB, use this QP which is the lowest non TQB QP tested (rather than QP'=0) - that way delta QPs are smaller, and TQB can be tested at all CU levels. if ( (pps.getTransquantBypassEnabledFlag()) ) { isAddLowestQP = true; // mark that the first iteration is to cost TQB mode. iMinQP = iMinQP - 1; // increase loop variable range by 1, to allow testing of TQB mode along with other QPs if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; } } TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx()); const Bool bBoundary = !( uiRPelX < sps.getPicWidthInLumaSamples() && uiBPelY < sps.getPicHeightInLumaSamples() ); if ( !bBoundary ) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } #if JVET_Y0077_BIM if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable() || m_pcEncCfg->getBIM()) && uiDepth <= pps.getMaxCuDQPDepth()) #else #if JVET_V0078 if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable()) && uiDepth <= pps.getMaxCuDQPDepth()) #else if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() && uiDepth <= pps.getMaxCuDQPDepth() ) #endif #endif { getSliceEncoder()->updateLambda(pcSlice, iQP); } m_cuChromaQpOffsetIdxPlus1 = 0; if (pcSlice->getUseChromaQpAdj()) { /* Pre-estimation of chroma QP based on input block activity may be performed * here, using for example m_ppcOrigYuv[uiDepth] */ /* To exercise the current code, the index used for adjustment is based on * block position */ Int lgMinCuSize = sps.getLog2MinCodingBlockSize() + std::max(0, sps.getLog2DiffMaxMinCodingBlockSize()-Int(pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth())); m_cuChromaQpOffsetIdxPlus1 = ((uiLPelX >> lgMinCuSize) + (uiTPelY >> lgMinCuSize)) % (pps.getPpsRangeExtension().getChromaQpOffsetListLen() + 1); } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, SKIP and 2Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N if(m_pcEncCfg->getUseEarlySkipDetection()) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );//by Competition for inter_2Nx2N } // SKIP xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU DEBUG_STRING_PASS_INTO(sDebug), &earlyDetectionSkipMode );//by Merge for inter_2Nx2N rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(!m_pcEncCfg->getUseEarlySkipDetection()) { // 2Nx2N, NxN xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode()) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } if (bIsLosslessMode) // Restore loop variable if lossless mode was searched. { iQP = iMinQP; } } if(!earlyDetectionSkipMode) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); // If lossless, then iQP is irrelevant for subsequent modules. if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, NxN, 2NxN, and Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N, NxN if(!( (rpcBestCU->getWidth(0)==8) && (rpcBestCU->getHeight(0)==8) )) { if( uiDepth == sps.getLog2DiffMaxMinCodingBlockSize() && doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_NxN DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter ( rpcBestCU, rpcTempCU, SIZE_2NxN DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxN) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } //! Try AMP (SIZE_2NxnU, SIZE_2NxnD, SIZE_nLx2N, SIZE_nRx2N) if(sps.getUseAMP() && uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) { #if AMP_ENC_SPEEDUP Bool bTestAMP_Hor = false, bTestAMP_Ver = false; #if AMP_MRG Bool bTestMergeAMP_Hor = false, bTestMergeAMP_Ver = false; deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver, bTestMergeAMP_Hor, bTestMergeAMP_Ver); #else deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver); #endif //! Do horizontal AMP if ( bTestAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #if AMP_MRG else if ( bTestMergeAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #endif //! Do horizontal AMP if ( bTestAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #if AMP_MRG else if ( bTestMergeAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N DEBUG_STRING_PASS_INTO(sDebug), true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #endif #else xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); #endif } } // do normal intra modes // speedup for inter frames #if MCTS_ENC_CHECK if ( m_pcEncCfg->getTMCTSSEITileConstraint() || (rpcBestCU->getSlice()->getSliceType() == I_SLICE) || ((!m_pcEncCfg->getDisableIntraPUsInInterSlices()) && ( (rpcBestCU->getCbf(0, COMPONENT_Y) != 0) || ((rpcBestCU->getCbf(0, COMPONENT_Cb) != 0) && (numberValidComponents > COMPONENT_Cb)) || ((rpcBestCU->getCbf(0, COMPONENT_Cr) != 0) && (numberValidComponents > COMPONENT_Cr)) // avoid very complex intra if it is unlikely ))) { #else if((rpcBestCU->getSlice()->getSliceType() == I_SLICE) || ((!m_pcEncCfg->getDisableIntraPUsInInterSlices()) && ( (rpcBestCU->getCbf( 0, COMPONENT_Y ) != 0) || ((rpcBestCU->getCbf( 0, COMPONENT_Cb ) != 0) && (numberValidComponents > COMPONENT_Cb)) || ((rpcBestCU->getCbf( 0, COMPONENT_Cr ) != 0) && (numberValidComponents > COMPONENT_Cr)) // avoid very complex intra if it is unlikely ))) { #endif xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if( uiDepth == sps.getLog2DiffMaxMinCodingBlockSize() ) { if( rpcTempCU->getWidth(0) > ( 1 << sps.getQuadtreeTULog2MinSize() ) ) { xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_NxN DEBUG_STRING_PASS_INTO(sDebug) ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } } // test PCM if(sps.getUsePCM() && rpcTempCU->getWidth(0) <= (1<getWidth(0) >= (1<getWidth(0), rpcBestCU->getHeight(0), rpcBestCU->getPic()->getChromaFormat(), sps.getBitDepths().recon); UInt uiBestBits = rpcBestCU->getTotalBits(); if((uiBestBits > uiRawBits) || (rpcBestCU->getTotalCost() > m_pcRdCost->calcRdCost(uiRawBits, 0))) { xCheckIntraPCM (rpcBestCU, rpcTempCU); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if (bIsLosslessMode) // Restore loop variable if lossless mode was searched. { iQP = iMinQP; } } } if( rpcBestCU->getTotalCost()!=MAX_DOUBLE ) { m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]); m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcBestCU, 0, uiDepth, true ); rpcBestCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcBestCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcBestCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcBestCU->getTotalBits(), rpcBestCU->getTotalDistortion() ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]); } } // copy original YUV samples to PCM buffer if( rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isLosslessCoded(0) && (rpcBestCU->getIPCMFlag(0) == false)) { xFillPCMBuffer(rpcBestCU, m_ppcOrigYuv[uiDepth]); } if( uiDepth == pps.getMaxCuDQPDepth() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP+idQP ); #if JVET_Y0077_BIM if (m_pcEncCfg->getBIM()) { std::map *QPmap = m_pcEncCfg->getAdaptQPmap(); Int iCTUoffset = uiTPelY / MAX_CU_SIZE * pcPic->getFrameWidthInCtus() + uiLPelX / MAX_CU_SIZE; Int iOffset = ( QPmap->find( pcPic->getPOC() ) == QPmap->end() ) ? 0 : (*QPmap)[pcPic->getPOC()][iCTUoffset]; iMinQP += iOffset; iMaxQP += iOffset; } #endif } else if( uiDepth < pps.getMaxCuDQPDepth() ) { iMinQP = iBaseQP; iMaxQP = iBaseQP; } else { const Int iStartQP = rpcTempCU->getQP(0); iMinQP = iStartQP; iMaxQP = iStartQP; } if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() ) { iMinQP = Clip3(-sps.getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQP - m_lumaQPOffset); iMaxQP = iMinQP; } if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; // If all TUs are forced into using transquant bypass, do not loop here. } const Bool bSubBranch = bBoundary || !( m_pcEncCfg->getUseEarlyCU() && rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isSkipped(0) ); if( bSubBranch && uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() && (!getFastDeltaQp() || uiWidth > fastDeltaQPCuMaxSize || bBoundary)) { // further split Double splitTotalCost = 0; for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = false; // False at this level. Next level down may set it to true. rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); UChar uhNextDepth = uiDepth+1; TComDataCU* pcSubBestPartCU = m_ppcBestCU[uhNextDepth]; TComDataCU* pcSubTempPartCU = m_ppcTempCU[uhNextDepth]; DEBUG_STRING_NEW(sTempDebug) for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ ) { pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. if( ( pcSubBestPartCU->getCUPelX() < sps.getPicWidthInLumaSamples() ) && ( pcSubBestPartCU->getCUPelY() < sps.getPicHeightInLumaSamples() ) ) { if ( 0 == uiPartUnitIdx) //initialize RD with previous depth buffer { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } else { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); } #if AMP_ENC_SPEEDUP DEBUG_STRING_NEW(sChild) if ( !(rpcBestCU->getTotalCost()!=MAX_DOUBLE && rpcBestCU->isInter(0)) ) { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth DEBUG_STRING_PASS_INTO(sChild), NUMBER_OF_PART_SIZES ); } else { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth DEBUG_STRING_PASS_INTO(sChild), rpcBestCU->getPartitionSize(0) ); } DEBUG_STRING_APPEND(sTempDebug, sChild) #else xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth ); #endif rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); // Keep best part data to current temporary data. xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth ); #if JVET_Y0077_BIM if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable() || m_pcEncCfg->getBIM()) && pps.getMaxCuDQPDepth() >= 1) #else #if JVET_V0078 if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable()) && pps.getMaxCuDQPDepth() >= 1) #else if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() && pps.getMaxCuDQPDepth() >= 1 ) #endif #endif { splitTotalCost += pcSubBestPartCU->getTotalCost(); } } else { pcSubBestPartCU->copyToPic( uhNextDepth ); rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); } } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); if( !bBoundary ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcTempCU, 0, uiDepth, true ); #if JVET_Y0077_BIM if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable() || m_pcEncCfg->getBIM()) && pps.getMaxCuDQPDepth() >= 1) #else #if JVET_V0078 if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable()) && pps.getMaxCuDQPDepth() >= 1) #else if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() && pps.getMaxCuDQPDepth() >= 1 ) #endif #endif { Int splitBits = m_pcEntropyCoder->getNumberOfWrittenBits(); Double splitBitCost = m_pcRdCost->calcRdCost( splitBits, 0 ); splitTotalCost += splitBitCost; } rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); } #if JVET_Y0077_BIM if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable() || m_pcEncCfg->getBIM()) && pps.getMaxCuDQPDepth() >= 1) #else #if JVET_V0078 if ((m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || m_pcEncCfg->getSmoothQPReductionEnable()) && pps.getMaxCuDQPDepth() >= 1) #else if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() && pps.getMaxCuDQPDepth() >= 1 ) #endif #endif { rpcTempCU->getTotalCost() = splitTotalCost; } else { rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); } if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP()) { Bool hasResidual = false; for( UInt uiBlkIdx = 0; uiBlkIdx < rpcTempCU->getTotalNumPart(); uiBlkIdx ++) { if( ( rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Y) || (rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Cb) && (numberValidComponents > COMPONENT_Cb)) || (rpcTempCU->getCbf(uiBlkIdx, COMPONENT_Cr) && (numberValidComponents > COMPONENT_Cr)) ) ) { hasResidual = true; break; } } if ( hasResidual ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQP( rpcTempCU, 0, false ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // dQP bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); Bool foundNonZeroCbf = false; rpcTempCU->setQPSubCUs( rpcTempCU->getRefQP( 0 ), 0, uiDepth, foundNonZeroCbf ); assert( foundNonZeroCbf ); } else { rpcTempCU->setQPSubParts( rpcTempCU->getRefQP( 0 ), 0, uiDepth ); // set QP to default QP } } m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); // If the configuration being tested exceeds the maximum number of bytes for a slice / slice-segment, then // a proper RD evaluation cannot be performed. Therefore, termination of the // slice/slice-segment must be made prior to this CTU. // This can be achieved by forcing the decision to be that of the rpcTempCU. // The exception is each slice / slice-segment must have at least one CTU. if (rpcBestCU->getTotalCost()!=MAX_DOUBLE) { const Bool isEndOfSlice = pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES && ((pcSlice->getSliceBits()+rpcBestCU->getTotalBits())>pcSlice->getSliceArgument()<<3) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()); const Bool isEndOfSliceSegment = pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && ((pcSlice->getSliceSegmentBits()+rpcBestCU->getTotalBits()) > pcSlice->getSliceSegmentArgument()<<3) && rpcBestCU->getCtuRsAddr() != pcPic->getPicSym()->getCtuTsToRsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()); // Do not need to check slice condition for slice-segment since a slice-segment is a subset of a slice. if(isEndOfSlice||isEndOfSliceSegment) { rpcBestCU->getTotalCost()=MAX_DOUBLE; } } xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTempDebug) DEBUG_STRING_PASS_INTO(false) ); // RD compare current larger prediction // with sub partitioned prediction. } } DEBUG_STRING_APPEND(sDebug_, sDebug); rpcBestCU->copyToPic(uiDepth); // Copy Best data to Picture for next partition prediction. xCopyYuv2Pic( rpcBestCU->getPic(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu(), uiDepth, uiDepth ); // Copy Yuv data to picture Yuv if (bBoundary) { return; } // Assert if Best prediction mode is NONE // Selected mode's RD-cost must be not MAX_DOUBLE. assert( rpcBestCU->getPartitionSize ( 0 ) != NUMBER_OF_PART_SIZES ); assert( rpcBestCU->getPredictionMode( 0 ) != NUMBER_OF_PREDICTION_MODES ); assert( rpcBestCU->getTotalCost ( ) != MAX_DOUBLE ); } /** finish encoding a cu and handle end-of-slice conditions * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TEncCu::finishCU( TComDataCU* pcCU, UInt uiAbsPartIdx ) { TComPic* pcPic = pcCU->getPic(); TComSlice * pcSlice = pcCU->getPic()->getSlice(pcCU->getPic()->getCurrSliceIdx()); //Calculate end address const Int currentCTUTsAddr = pcPic->getPicSym()->getCtuRsToTsAddrMap(pcCU->getCtuRsAddr()); const Bool isLastSubCUOfCtu = pcCU->isLastSubCUOfCtu(uiAbsPartIdx); if ( isLastSubCUOfCtu ) { // The 1-terminating bit is added to all streams, so don't add it here when it's 1. // i.e. when the slice segment CurEnd CTU address is the current CTU address+1. if (pcSlice->getSliceSegmentCurEndCtuTsAddr() != currentCTUTsAddr+1) { m_pcEntropyCoder->encodeTerminatingBit( 0 ); } } } /** Compute QP for each CU * \param pcCU Target CU * \param uiDepth CU depth * \returns quantization parameter */ Int TEncCu::xComputeQP( TComDataCU* pcCU, UInt uiDepth ) { Int iBaseQp = pcCU->getSlice()->getSliceQp(); Int iQpOffset = 0; if ( m_pcEncCfg->getUseAdaptiveQP() ) { TEncPic* pcEPic = dynamic_cast( pcCU->getPic() ); UInt uiAQDepth = min( uiDepth, pcEPic->getMaxAQDepth()-1 ); TEncPicQPAdaptationLayer* pcAQLayer = pcEPic->getAQLayer( uiAQDepth ); UInt uiAQUPosX = pcCU->getCUPelX() / pcAQLayer->getAQPartWidth(); UInt uiAQUPosY = pcCU->getCUPelY() / pcAQLayer->getAQPartHeight(); UInt uiAQUStride = pcAQLayer->getAQPartStride(); TEncQPAdaptationUnit* acAQU = pcAQLayer->getQPAdaptationUnit(); Double dMaxQScale = pow(2.0, m_pcEncCfg->getQPAdaptationRange()/6.0); Double dAvgAct = pcAQLayer->getAvgActivity(); Double dCUAct = acAQU[uiAQUPosY * uiAQUStride + uiAQUPosX].getActivity(); Double dNormAct = (dMaxQScale*dCUAct + dAvgAct) / (dCUAct + dMaxQScale*dAvgAct); Double dQpOffset = log(dNormAct) / log(2.0) * 6.0; iQpOffset = Int(floor( dQpOffset + 0.49999 )); } return Clip3(-pcCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, iBaseQp+iQpOffset ); } /** encode a CU block recursively * \param pcCU * \param uiAbsPartIdx * \param uiDepth * \returns Void */ Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { TComPic *const pcPic = pcCU->getPic(); TComSlice *const pcSlice = pcCU->getSlice(); const TComSPS &sps =*(pcSlice->getSPS()); const TComPPS &pps =*(pcSlice->getPPS()); const UInt maxCUWidth = sps.getMaxCUWidth(); const UInt maxCUHeight = sps.getMaxCUHeight(); Bool bBoundary = false; UInt uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; const UInt uiRPelX = uiLPelX + (maxCUWidth>>uiDepth) - 1; UInt uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ]; const UInt uiBPelY = uiTPelY + (maxCUHeight>>uiDepth) - 1; if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) ) { m_pcEntropyCoder->encodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth ); } else { bBoundary = true; } if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary ) { UInt uiQNumParts = ( pcPic->getNumPartitionsInCtu() >> (uiDepth<<1) )>>2; if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP()) { setdQPFlag(true); } if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()) { setCodeChromaQpAdjFlag(true); } for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts ) { uiLPelX = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; uiTPelY = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ]; if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) ) { xEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1 ); } } return; } if( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP()) { setdQPFlag(true); } if( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj()) { setCodeChromaQpAdjFlag(true); } if (pps.getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx ); } if( !pcSlice->isIntra() ) { m_pcEntropyCoder->encodeSkipFlag( pcCU, uiAbsPartIdx ); } if( pcCU->isSkipped( uiAbsPartIdx ) ) { m_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx ); finishCU(pcCU,uiAbsPartIdx); return; } m_pcEntropyCoder->encodePredMode( pcCU, uiAbsPartIdx ); m_pcEntropyCoder->encodePartSize( pcCU, uiAbsPartIdx, uiDepth ); if (pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N ) { m_pcEntropyCoder->encodeIPCMInfo( pcCU, uiAbsPartIdx ); if(pcCU->getIPCMFlag(uiAbsPartIdx)) { // Encode slice finish finishCU(pcCU,uiAbsPartIdx); return; } } // prediction Info ( Intra : direction mode, Inter : Mv, reference idx ) m_pcEntropyCoder->encodePredInfo( pcCU, uiAbsPartIdx ); // Encode Coefficients Bool bCodeDQP = getdQPFlag(); Bool codeChromaQpAdj = getCodeChromaQpAdjFlag(); m_pcEntropyCoder->encodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, codeChromaQpAdj ); setCodeChromaQpAdjFlag( codeChromaQpAdj ); setdQPFlag( bCodeDQP ); // --- write terminating bit --- finishCU(pcCU,uiAbsPartIdx); } Int xCalcHADs8x8_ISlice(Pel *piOrg, Int iStrideOrg) { Int k, i, j, jj; Int diff[64], m1[8][8], m2[8][8], m3[8][8], iSumHad = 0; for( k = 0; k < 64; k += 8 ) { diff[k+0] = piOrg[0] ; diff[k+1] = piOrg[1] ; diff[k+2] = piOrg[2] ; diff[k+3] = piOrg[3] ; diff[k+4] = piOrg[4] ; diff[k+5] = piOrg[5] ; diff[k+6] = piOrg[6] ; diff[k+7] = piOrg[7] ; piOrg += iStrideOrg; } //horizontal for (j=0; j < 8; j++) { jj = j << 3; m2[j][0] = diff[jj ] + diff[jj+4]; m2[j][1] = diff[jj+1] + diff[jj+5]; m2[j][2] = diff[jj+2] + diff[jj+6]; m2[j][3] = diff[jj+3] + diff[jj+7]; m2[j][4] = diff[jj ] - diff[jj+4]; m2[j][5] = diff[jj+1] - diff[jj+5]; m2[j][6] = diff[jj+2] - diff[jj+6]; m2[j][7] = diff[jj+3] - diff[jj+7]; m1[j][0] = m2[j][0] + m2[j][2]; m1[j][1] = m2[j][1] + m2[j][3]; m1[j][2] = m2[j][0] - m2[j][2]; m1[j][3] = m2[j][1] - m2[j][3]; m1[j][4] = m2[j][4] + m2[j][6]; m1[j][5] = m2[j][5] + m2[j][7]; m1[j][6] = m2[j][4] - m2[j][6]; m1[j][7] = m2[j][5] - m2[j][7]; m2[j][0] = m1[j][0] + m1[j][1]; m2[j][1] = m1[j][0] - m1[j][1]; m2[j][2] = m1[j][2] + m1[j][3]; m2[j][3] = m1[j][2] - m1[j][3]; m2[j][4] = m1[j][4] + m1[j][5]; m2[j][5] = m1[j][4] - m1[j][5]; m2[j][6] = m1[j][6] + m1[j][7]; m2[j][7] = m1[j][6] - m1[j][7]; } //vertical for (i=0; i < 8; i++) { m3[0][i] = m2[0][i] + m2[4][i]; m3[1][i] = m2[1][i] + m2[5][i]; m3[2][i] = m2[2][i] + m2[6][i]; m3[3][i] = m2[3][i] + m2[7][i]; m3[4][i] = m2[0][i] - m2[4][i]; m3[5][i] = m2[1][i] - m2[5][i]; m3[6][i] = m2[2][i] - m2[6][i]; m3[7][i] = m2[3][i] - m2[7][i]; m1[0][i] = m3[0][i] + m3[2][i]; m1[1][i] = m3[1][i] + m3[3][i]; m1[2][i] = m3[0][i] - m3[2][i]; m1[3][i] = m3[1][i] - m3[3][i]; m1[4][i] = m3[4][i] + m3[6][i]; m1[5][i] = m3[5][i] + m3[7][i]; m1[6][i] = m3[4][i] - m3[6][i]; m1[7][i] = m3[5][i] - m3[7][i]; m2[0][i] = m1[0][i] + m1[1][i]; m2[1][i] = m1[0][i] - m1[1][i]; m2[2][i] = m1[2][i] + m1[3][i]; m2[3][i] = m1[2][i] - m1[3][i]; m2[4][i] = m1[4][i] + m1[5][i]; m2[5][i] = m1[4][i] - m1[5][i]; m2[6][i] = m1[6][i] + m1[7][i]; m2[7][i] = m1[6][i] - m1[7][i]; } for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { iSumHad += abs(m2[i][j]); } } iSumHad -= abs(m2[0][0]); iSumHad =(iSumHad+2)>>2; return(iSumHad); } Int TEncCu::updateCtuDataISlice(TComDataCU* pCtu, Int width, Int height) { Int xBl, yBl; const Int iBlkSize = 8; Pel* pOrgInit = pCtu->getPic()->getPicYuvOrg()->getAddr(COMPONENT_Y, pCtu->getCtuRsAddr(), 0); Int iStrideOrig = pCtu->getPic()->getPicYuvOrg()->getStride(COMPONENT_Y); Pel *pOrg; Int iSumHad = 0; for ( yBl=0; (yBl+iBlkSize)<=height; yBl+= iBlkSize) { for ( xBl=0; (xBl+iBlkSize)<=width; xBl+= iBlkSize) { pOrg = pOrgInit + iStrideOrig*yBl + xBl; iSumHad += xCalcHADs8x8_ISlice(pOrg, iStrideOrig); } } return(iSumHad); } /** check RD costs for a CU block encoded with merge * \param rpcBestCU * \param rpcTempCU * \param earlyDetectionSkipMode */ Void TEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU DEBUG_STRING_FN_DECLARE(sDebug), Bool *earlyDetectionSkipMode ) { assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE ); if(getFastDeltaQp()) { return; // never check merge in fast deltaqp mode } TComMvField cMvFieldNeighbours[2 * MRG_MAX_NUM_CANDS]; // double length for mv of both lists UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS]; Int numValidMergeCand = 0; const Bool bTransquantBypassFlag = rpcTempCU->getCUTransquantBypass(0); for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui ) { uhInterDirNeighbours[ui] = 0; } UChar uhDepth = rpcTempCU->getDepth( 0 ); rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to CTU level #if MCTS_ENC_CHECK UInt numSpatialMergeCandidates = 0; rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates ); #else rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand ); #endif Int mergeCandBuffer[MRG_MAX_NUM_CANDS]; for( UInt ui = 0; ui < numValidMergeCand; ++ui ) { mergeCandBuffer[ui] = 0; } #if MCTS_ENC_CHECK if (m_pcEncCfg->getTMCTSSEITileConstraint() && rpcTempCU->isLastColumnCTUInTile()) { numValidMergeCand = numSpatialMergeCandidates; } #endif Bool bestIsSkip = false; UInt iteration; if ( rpcTempCU->isLosslessCoded(0)) { iteration = 1; } else { iteration = 2; } DEBUG_STRING_NEW(bestStr) for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual ) { for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand ) { if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1)) { if( !(bestIsSkip && uiNoResidual == 0) ) { DEBUG_STRING_NEW(tmpStr) // set MC parameters rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to CTU level rpcTempCU->setCUTransquantBypassSubParts( bTransquantBypassFlag, 0, uhDepth ); rpcTempCU->setChromaQpAdjSubParts( bTransquantBypassFlag ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth ); rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to CTU level rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth ); // interprets depth relative to CTU level rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth ); // interprets depth relative to CTU level rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth ); // interprets depth relative to CTU level rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level #if MCTS_ENC_CHECK if ( m_pcEncCfg->getTMCTSSEITileConstraint () && (!(m_pcPredSearch->checkTMctsMvp(rpcTempCU)))) { continue; } #endif // do MC m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] ); // estimate residual and encode everything m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU, m_ppcOrigYuv [uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcResiYuvBest[uhDepth], m_ppcRecoYuvTemp[uhDepth], (uiNoResidual != 0) DEBUG_STRING_PASS_INTO(tmpStr) ); #if DEBUG_STRING DebugInterPredResiReco(tmpStr, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0))); #endif if ((uiNoResidual == 0) && (rpcTempCU->getQtRootCbf(0) == 0)) { // If no residual when allowing for one, then set mark to not try case where residual is forced to 0 mergeCandBuffer[uiMergeCand] = 1; } Int orgQP = rpcTempCU->getQP( 0 ); xCheckDQP( rpcTempCU ); xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth DEBUG_STRING_PASS_INTO(bestStr) DEBUG_STRING_PASS_INTO(tmpStr)); rpcTempCU->initEstData( uhDepth, orgQP, bTransquantBypassFlag ); if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) { bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0; } } } } if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection()) { if(rpcBestCU->getQtRootCbf( 0 ) == 0) { if( rpcBestCU->getMergeFlag( 0 )) { *earlyDetectionSkipMode = true; } else if(m_pcEncCfg->getMotionEstimationSearchMethod() != MESEARCH_SELECTIVE) { Int absoulte_MV=0; for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( rpcBestCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { TComCUMvField* pcCUMvField = rpcBestCU->getCUMvField(RefPicList( uiRefListIdx )); Int iHor = pcCUMvField->getMvd( 0 ).getAbsHor(); Int iVer = pcCUMvField->getMvd( 0 ).getAbsVer(); absoulte_MV+=iHor+iVer; } } if(absoulte_MV == 0) { *earlyDetectionSkipMode = true; } } } } } DEBUG_STRING_APPEND(sDebug, bestStr) } #if AMP_MRG Void TEncCu::xCheckRDCostInter( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseMRG) #else Void TEncCu::xCheckRDCostInter( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize ) #endif { DEBUG_STRING_NEW(sTest) if(getFastDeltaQp()) { const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMaxCUHeight()>>(sps.getLog2DiffMaxMinCodingBlockSize()), sps.getMaxCUHeight(), 32u); if(ePartSize != SIZE_2Nx2N || rpcTempCU->getWidth( 0 ) > fastDeltaQPCuMaxSize) { return; // only check necessary 2Nx2N Inter in fast deltaqp mode } } // prior to this, rpcTempCU will have just been reset using rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); UChar uhDepth = rpcTempCU->getDepth( 0 ); rpcTempCU->setPartSizeSubParts ( ePartSize, 0, uhDepth ); rpcTempCU->setPredModeSubParts ( MODE_INTER, 0, uhDepth ); rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth ); #if MCTS_ENC_CHECK rpcTempCU->setTMctsMvpIsValid(true); #endif #if AMP_MRG rpcTempCU->setMergeAMP (true); m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth] DEBUG_STRING_PASS_INTO(sTest), false, bUseMRG ); #else m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth] ); #endif #if AMP_MRG if ( !rpcTempCU->getMergeAMP() ) { return; } #endif #if MCTS_ENC_CHECK if (m_pcEncCfg->getTMCTSSEITileConstraint() && (!rpcTempCU->getTMctsMvpIsValid())) { return; } #endif m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcResiYuvBest[uhDepth], m_ppcRecoYuvTemp[uhDepth], false DEBUG_STRING_PASS_INTO(sTest) ); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); #if DEBUG_STRING DebugInterPredResiReco(sTest, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0))); #endif xCheckDQP( rpcTempCU ); xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTest)); } Void TEncCu::xCheckRDCostIntra( TComDataCU *&rpcBestCU, TComDataCU *&rpcTempCU, PartSize eSize DEBUG_STRING_FN_DECLARE(sDebug) ) { DEBUG_STRING_NEW(sTest) if(getFastDeltaQp()) { const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMaxCUHeight()>>(sps.getLog2DiffMaxMinCodingBlockSize()), sps.getMaxCUHeight(), 32u); if(rpcTempCU->getWidth( 0 ) > fastDeltaQPCuMaxSize) { return; // only check necessary 2Nx2N Intra in fast deltaqp mode } } UInt uiDepth = rpcTempCU->getDepth( 0 ); rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth ); rpcTempCU->setPartSizeSubParts( eSize, 0, uiDepth ); rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth ); rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uiDepth ); Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE]; m_pcPredSearch->estIntraPredLumaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], resiLuma DEBUG_STRING_PASS_INTO(sTest) ); m_ppcRecoYuvTemp[uiDepth]->copyToPicComponent(COMPONENT_Y, rpcTempCU->getPic()->getPicYuvRec(), rpcTempCU->getCtuRsAddr(), rpcTempCU->getZorderIdxInCtu() ); if (rpcBestCU->getPic()->getChromaFormat()!=CHROMA_400) { m_pcPredSearch->estIntraPredChromaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], resiLuma DEBUG_STRING_PASS_INTO(sTest) ); } m_pcEntropyCoder->resetBits(); if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0, true ); } m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0, true ); m_pcEntropyCoder->encodePredMode( rpcTempCU, 0, true ); m_pcEntropyCoder->encodePartSize( rpcTempCU, 0, uiDepth, true ); m_pcEntropyCoder->encodePredInfo( rpcTempCU, 0 ); m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, 0, true ); // Encode Coefficients Bool bCodeDQP = getdQPFlag(); Bool codeChromaQpAdjFlag = getCodeChromaQpAdjFlag(); m_pcEntropyCoder->encodeCoeff( rpcTempCU, 0, uiDepth, bCodeDQP, codeChromaQpAdjFlag ); setCodeChromaQpAdjFlag( codeChromaQpAdjFlag ); setdQPFlag( bCodeDQP ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits(); rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); xCheckDQP( rpcTempCU ); xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTest)); } /** Check R-D costs for a CU with PCM mode. * \param rpcBestCU pointer to best mode CU data structure * \param rpcTempCU pointer to testing mode CU data structure * \returns Void * * \note Current PCM implementation encodes sample values in a lossless way. The distortion of PCM mode CUs are zero. PCM mode is selected if the best mode yields bits greater than that of PCM mode. */ Void TEncCu::xCheckIntraPCM( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU ) { if(getFastDeltaQp()) { const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); const UInt fastDeltaQPCuMaxPCMSize = Clip3((UInt)1<getWidth( 0 ) > fastDeltaQPCuMaxPCMSize) { return; // only check necessary PCM in fast deltaqp mode } } UInt uiDepth = rpcTempCU->getDepth( 0 ); rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth ); rpcTempCU->setIPCMFlag(0, true); rpcTempCU->setIPCMFlagSubParts (true, 0, rpcTempCU->getDepth(0)); rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uiDepth ); rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth ); rpcTempCU->setTrIdxSubParts ( 0, 0, uiDepth ); rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uiDepth ); m_pcPredSearch->IPCMSearch( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth]); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); m_pcEntropyCoder->resetBits(); if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0, true ); } m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0, true ); m_pcEntropyCoder->encodePredMode ( rpcTempCU, 0, true ); m_pcEntropyCoder->encodePartSize ( rpcTempCU, 0, uiDepth, true ); m_pcEntropyCoder->encodeIPCMInfo ( rpcTempCU, 0, true ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits(); rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); xCheckDQP( rpcTempCU ); DEBUG_STRING_NEW(a) DEBUG_STRING_NEW(b) xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(a) DEBUG_STRING_PASS_INTO(b)); } /** check whether current try is the best with identifying the depth of current try * \param rpcBestCU * \param rpcTempCU * \param uiDepth */ Void TEncCu::xCheckBestMode( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth DEBUG_STRING_FN_DECLARE(sParent) DEBUG_STRING_FN_DECLARE(sTest) DEBUG_STRING_PASS_INTO(Bool bAddSizeInfo) ) { if( rpcTempCU->getTotalCost() < rpcBestCU->getTotalCost() ) { TComYuv* pcYuv; // Change Information data TComDataCU* pcCU = rpcBestCU; rpcBestCU = rpcTempCU; rpcTempCU = pcCU; // Change Prediction data pcYuv = m_ppcPredYuvBest[uiDepth]; m_ppcPredYuvBest[uiDepth] = m_ppcPredYuvTemp[uiDepth]; m_ppcPredYuvTemp[uiDepth] = pcYuv; // Change Reconstruction data pcYuv = m_ppcRecoYuvBest[uiDepth]; m_ppcRecoYuvBest[uiDepth] = m_ppcRecoYuvTemp[uiDepth]; m_ppcRecoYuvTemp[uiDepth] = pcYuv; pcYuv = NULL; pcCU = NULL; // store temp best CI for next CU coding m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]->store(m_pppcRDSbacCoder[uiDepth][CI_NEXT_BEST]); #if DEBUG_STRING DEBUG_STRING_SWAP(sParent, sTest) const PredMode predMode=rpcBestCU->getPredictionMode(0); if ((DebugOptionList::DebugString_Structure.getInt()&DebugStringGetPredModeMask(predMode)) && bAddSizeInfo) { std::stringstream ss(stringstream::out); ss <<"###: " << (predMode==MODE_INTRA?"Intra ":"Inter ") << partSizeToString[rpcBestCU->getPartitionSize(0)] << " CU at " << rpcBestCU->getCUPelX() << ", " << rpcBestCU->getCUPelY() << " width=" << UInt(rpcBestCU->getWidth(0)) << std::endl; sParent+=ss.str(); } #endif } } Void TEncCu::xCheckDQP( TComDataCU* pcCU ) { UInt uiDepth = pcCU->getDepth( 0 ); const TComPPS &pps = *(pcCU->getSlice()->getPPS()); if ( pps.getUseDQP() && uiDepth <= pps.getMaxCuDQPDepth() ) { if ( pcCU->getQtRootCbf( 0) ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQP( pcCU, 0, false ); pcCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // dQP bits pcCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); pcCU->getTotalCost() = m_pcRdCost->calcRdCost( pcCU->getTotalBits(), pcCU->getTotalDistortion() ); } else { pcCU->setQPSubParts( pcCU->getRefQP( 0 ), 0, uiDepth ); // set QP to default QP } } } Void TEncCu::xCopyAMVPInfo (AMVPInfo* pSrc, AMVPInfo* pDst) { pDst->iN = pSrc->iN; for (Int i = 0; i < pSrc->iN; i++) { pDst->m_acMvCand[i] = pSrc->m_acMvCand[i]; } } Void TEncCu::xCopyYuv2Pic(TComPic* rpcPic, UInt uiCUAddr, UInt uiAbsPartIdx, UInt uiDepth, UInt uiSrcDepth ) { UInt uiAbsPartIdxInRaster = g_auiZscanToRaster[uiAbsPartIdx]; UInt uiSrcBlkWidth = rpcPic->getNumPartInCtuWidth() >> (uiSrcDepth); UInt uiBlkWidth = rpcPic->getNumPartInCtuWidth() >> (uiDepth); UInt uiPartIdxX = ( ( uiAbsPartIdxInRaster % rpcPic->getNumPartInCtuWidth() ) % uiSrcBlkWidth) / uiBlkWidth; UInt uiPartIdxY = ( ( uiAbsPartIdxInRaster / rpcPic->getNumPartInCtuWidth() ) % uiSrcBlkWidth) / uiBlkWidth; UInt uiPartIdx = uiPartIdxY * ( uiSrcBlkWidth / uiBlkWidth ) + uiPartIdxX; m_ppcRecoYuvBest[uiSrcDepth]->copyToPicYuv( rpcPic->getPicYuvRec (), uiCUAddr, uiAbsPartIdx, uiDepth - uiSrcDepth, uiPartIdx); m_ppcPredYuvBest[uiSrcDepth]->copyToPicYuv( rpcPic->getPicYuvPred (), uiCUAddr, uiAbsPartIdx, uiDepth - uiSrcDepth, uiPartIdx); } Void TEncCu::xCopyYuv2Tmp( UInt uiPartUnitIdx, UInt uiNextDepth ) { UInt uiCurrDepth = uiNextDepth - 1; m_ppcRecoYuvBest[uiNextDepth]->copyToPartYuv( m_ppcRecoYuvTemp[uiCurrDepth], uiPartUnitIdx ); m_ppcPredYuvBest[uiNextDepth]->copyToPartYuv( m_ppcPredYuvBest[uiCurrDepth], uiPartUnitIdx); } /** Function for filling the PCM buffer of a CU using its original sample array * \param pCU pointer to current CU * \param pOrgYuv pointer to original sample array */ Void TEncCu::xFillPCMBuffer ( TComDataCU* pCU, TComYuv* pOrgYuv ) { const ChromaFormat format = pCU->getPic()->getChromaFormat(); const UInt numberValidComponents = getNumberValidComponents(format); for (UInt componentIndex = 0; componentIndex < numberValidComponents; componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt width = pCU->getWidth(0) >> getComponentScaleX(component, format); const UInt height = pCU->getHeight(0) >> getComponentScaleY(component, format); Pel *source = pOrgYuv->getAddr(component, 0, width); Pel *destination = pCU->getPCMSample(component); const UInt sourceStride = pOrgYuv->getStride(component); for (Int line = 0; line < height; line++) { for (Int column = 0; column < width; column++) { destination[column] = source[column]; } source += sourceStride; destination += width; } } } #if ADAPTIVE_QP_SELECTION /** Collect ARL statistics from one block */ Int TEncCu::xTuCollectARLStats(TCoeff* rpcCoeff, TCoeff* rpcArlCoeff, Int NumCoeffInCU, Double* cSum, UInt* numSamples ) { for( Int n = 0; n < NumCoeffInCU; n++ ) { TCoeff u = abs( rpcCoeff[ n ] ); TCoeff absc = rpcArlCoeff[ n ]; if( u != 0 ) { if( u < LEVEL_RANGE ) { cSum[ u ] += ( Double )absc; numSamples[ u ]++; } else { cSum[ LEVEL_RANGE ] += ( Double )absc - ( Double )( u << ARL_C_PRECISION ); numSamples[ LEVEL_RANGE ]++; } } } return 0; } //! Collect ARL statistics from one CTU Void TEncCu::xCtuCollectARLStats(TComDataCU* pCtu ) { Double cSum[ LEVEL_RANGE + 1 ]; //: the sum of DCT coefficients corresponding to data type and quantization output UInt numSamples[ LEVEL_RANGE + 1 ]; //: the number of coefficients corresponding to data type and quantization output TCoeff* pCoeffY = pCtu->getCoeff(COMPONENT_Y); TCoeff* pArlCoeffY = pCtu->getArlCoeff(COMPONENT_Y); const TComSPS &sps = *(pCtu->getSlice()->getSPS()); const UInt uiMinCUWidth = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); // NOTE: ed - this is not the minimum CU width. It is the square-root of the number of coefficients per part. const UInt uiMinNumCoeffInCU = 1 << uiMinCUWidth; // NOTE: ed - what is this? memset( cSum, 0, sizeof( Double )*(LEVEL_RANGE+1) ); memset( numSamples, 0, sizeof( UInt )*(LEVEL_RANGE+1) ); // Collect stats to cSum[][] and numSamples[][] for(Int i = 0; i < pCtu->getTotalNumPart(); i ++ ) { UInt uiTrIdx = pCtu->getTransformIdx(i); if(pCtu->isInter(i) && pCtu->getCbf( i, COMPONENT_Y, uiTrIdx ) ) { xTuCollectARLStats(pCoeffY, pArlCoeffY, uiMinNumCoeffInCU, cSum, numSamples); }//Note that only InterY is processed. QP rounding is based on InterY data only. pCoeffY += uiMinNumCoeffInCU; pArlCoeffY += uiMinNumCoeffInCU; } for(Int u=1; ugetSliceSumC()[u] += cSum[ u ] ; m_pcTrQuant->getSliceNSamples()[u] += numSamples[ u ] ; } m_pcTrQuant->getSliceSumC()[LEVEL_RANGE] += cSum[ LEVEL_RANGE ] ; m_pcTrQuant->getSliceNSamples()[LEVEL_RANGE] += numSamples[ LEVEL_RANGE ] ; } #endif //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncCu.h000066400000000000000000000206441442026013100177010ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncCu.h \brief Coding Unit (CU) encoder class (header) */ #ifndef __TENCCU__ #define __TENCCU__ // Include files #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComYuv.h" #include "TLibCommon/TComPrediction.h" #include "TLibCommon/TComTrQuant.h" #include "TLibCommon/TComBitCounter.h" #include "TLibCommon/TComDataCU.h" #include "TEncEntropy.h" #include "TEncSearch.h" #include "TEncRateCtrl.h" //! \ingroup TLibEncoder //! \{ class TEncTop; class TEncSbac; class TEncCavlc; class TEncSlice; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// CU encoder class class TEncCu { private: TComDataCU** m_ppcBestCU; ///< Best CUs in each depth TComDataCU** m_ppcTempCU; ///< Temporary CUs in each depth UChar m_uhTotalDepth; TComYuv** m_ppcPredYuvBest; ///< Best Prediction Yuv for each depth TComYuv** m_ppcResiYuvBest; ///< Best Residual Yuv for each depth TComYuv** m_ppcRecoYuvBest; ///< Best Reconstruction Yuv for each depth TComYuv** m_ppcPredYuvTemp; ///< Temporary Prediction Yuv for each depth TComYuv** m_ppcResiYuvTemp; ///< Temporary Residual Yuv for each depth TComYuv** m_ppcRecoYuvTemp; ///< Temporary Reconstruction Yuv for each depth TComYuv** m_ppcOrigYuv; ///< Original Yuv for each depth // Data : encoder control Bool m_bEncodeDQP; Bool m_bFastDeltaQP; Bool m_stillToCodeChromaQpOffsetFlag; //indicates whether chroma QP offset flag needs to coded at this particular CU granularity. Int m_cuChromaQpOffsetIdxPlus1; // if 0, then cu_chroma_qp_offset_flag will be 0, otherwise cu_chroma_qp_offset_flag will be 1. Int m_lumaLevelToDeltaQPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE]; Int m_lumaQPOffset; TEncSlice* m_pcSliceEncoder; #if JVET_V0078 Int m_smoothQPoffset; #endif #if JVET_Y0077_BIM Int m_BimQPoffset; #endif // Access channel TEncCfg* m_pcEncCfg; TEncSearch* m_pcPredSearch; TComTrQuant* m_pcTrQuant; TComRdCost* m_pcRdCost; TEncEntropy* m_pcEntropyCoder; TEncBinCABAC* m_pcBinCABAC; // SBAC RD TEncSbac*** m_pppcRDSbacCoder; TEncSbac* m_pcRDGoOnSbacCoder; TEncRateCtrl* m_pcRateCtrl; public: /// copy parameters from encoder class Void init ( TEncTop* pcEncTop ); Void setSliceEncoder( TEncSlice* pSliceEncoder ) { m_pcSliceEncoder = pSliceEncoder; } TEncSlice* getSliceEncoder() { return m_pcSliceEncoder; } Void initLumaDeltaQpLUT(); Int calculateLumaDQP( TComDataCU *pCU, const UInt absPartIdx, const TComYuv * pOrgYuv ); #if JVET_V0078 Int calculateLumaDQPsmooth(TComDataCU *pCU, const UInt absPartIdx, const TComYuv * pOrgYuv, Int iBaseQP); #endif /// create internal buffers Void create ( UChar uhTotalDepth, UInt iMaxWidth, UInt iMaxHeight, ChromaFormat chromaFormat ); /// destroy internal buffers Void destroy (); /// CTU analysis function Void compressCtu ( TComDataCU* pCtu ); /// CTU encoding function Void encodeCtu ( TComDataCU* pCtu ); Int updateCtuDataISlice ( TComDataCU* pCtu, Int width, Int height ); Void setFastDeltaQp ( Bool b) { m_bFastDeltaQP = b; } protected: Void finishCU ( TComDataCU* pcCU, UInt uiAbsPartIdx ); #if AMP_ENC_SPEEDUP Void xCompressCU ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth DEBUG_STRING_FN_DECLARE(sDebug), PartSize eParentPartSize = NUMBER_OF_PART_SIZES ); #else Void xCompressCU ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth ); #endif Void xEncodeCU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ); Int xComputeQP ( TComDataCU* pcCU, UInt uiDepth ); Void xCheckBestMode ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth DEBUG_STRING_FN_DECLARE(sParent) DEBUG_STRING_FN_DECLARE(sTest) DEBUG_STRING_PASS_INTO(Bool bAddSizeInfo=true)); Void xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU DEBUG_STRING_FN_DECLARE(sDebug), Bool *earlyDetectionSkipMode ); #if AMP_MRG Void xCheckRDCostInter ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseMRG = false ); #else Void xCheckRDCostInter ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize ); #endif Void xCheckRDCostIntra ( TComDataCU *&rpcBestCU, TComDataCU *&rpcTempCU, PartSize ePartSize DEBUG_STRING_FN_DECLARE(sDebug) ); Void xCheckDQP ( TComDataCU* pcCU ); Void xCheckIntraPCM ( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU ); Void xCopyAMVPInfo ( AMVPInfo* pSrc, AMVPInfo* pDst ); Void xCopyYuv2Pic (TComPic* rpcPic, UInt uiCUAddr, UInt uiAbsPartIdx, UInt uiDepth, UInt uiSrcDepth ); Void xCopyYuv2Tmp ( UInt uhPartUnitIdx, UInt uiDepth ); Bool getdQPFlag () { return m_bEncodeDQP; } Void setdQPFlag ( Bool b ) { m_bEncodeDQP = b; } Bool getFastDeltaQp () const { return m_bFastDeltaQP; } Bool getCodeChromaQpAdjFlag() { return m_stillToCodeChromaQpOffsetFlag; } Void setCodeChromaQpAdjFlag( Bool b ) { m_stillToCodeChromaQpOffsetFlag = b; } #if ADAPTIVE_QP_SELECTION // Adaptive reconstruction level (ARL) statistics collection functions Void xCtuCollectARLStats(TComDataCU* pCtu); Int xTuCollectARLStats(TCoeff* rpcCoeff, TCoeff* rpcArlCoeff, Int NumCoeffInCU, Double* cSum, UInt* numSamples ); #endif #if AMP_ENC_SPEEDUP #if AMP_MRG Void deriveTestModeAMP (TComDataCU *pcBestCU, PartSize eParentPartSize, Bool &bTestAMP_Hor, Bool &bTestAMP_Ver, Bool &bTestMergeAMP_Hor, Bool &bTestMergeAMP_Ver); #else Void deriveTestModeAMP (TComDataCU *pcBestCU, PartSize eParentPartSize, Bool &bTestAMP_Hor, Bool &bTestAMP_Ver); #endif #endif Void xFillPCMBuffer ( TComDataCU* pCU, TComYuv* pOrgYuv ); }; //! \} #endif // __TENCMB__ HM-HM-18.0/source/Lib/TLibEncoder/TEncEntropy.cpp000066400000000000000000000520301442026013100213170ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncEntropy.cpp \brief entropy encoder class */ #include "TEncEntropy.h" #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComSampleAdaptiveOffset.h" #include "TLibCommon/TComTU.h" #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST #include "../TLibCommon/Debug.h" static const Bool bDebugPredEnabled = DebugOptionList::DebugPred.getInt()!=0; #endif //! \ingroup TLibEncoder //! \{ Void TEncEntropy::setEntropyCoder ( TEncEntropyIf* e ) { m_pcEntropyCoderIf = e; } Void TEncEntropy::encodeSliceHeader ( TComSlice* pcSlice ) { m_pcEntropyCoderIf->codeSliceHeader( pcSlice ); return; } Void TEncEntropy::encodeTilesWPPEntryPoint( TComSlice* pSlice ) { m_pcEntropyCoderIf->codeTilesWPPEntryPoint( pSlice ); } Void TEncEntropy::encodeTerminatingBit ( UInt uiIsLast ) { m_pcEntropyCoderIf->codeTerminatingBit( uiIsLast ); return; } Void TEncEntropy::encodeSliceFinish() { m_pcEntropyCoderIf->codeSliceFinish(); } Void TEncEntropy::encodePPS( const TComPPS* pcPPS ) { m_pcEntropyCoderIf->codePPS( pcPPS ); return; } Void TEncEntropy::encodeSPS( const TComSPS* pcSPS ) { m_pcEntropyCoderIf->codeSPS( pcSPS ); return; } Void TEncEntropy::encodeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeCUTransquantBypassFlag( pcCU, uiAbsPartIdx ); } Void TEncEntropy::encodeVPS( const TComVPS* pcVPS ) { m_pcEntropyCoderIf->codeVPS( pcVPS ); return; } Void TEncEntropy::encodeSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if ( pcCU->getSlice()->isIntra() ) { return; } if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeSkipFlag( pcCU, uiAbsPartIdx ); } //! encode merge flag Void TEncEntropy::encodeMergeFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) { // at least one merge candidate exists m_pcEntropyCoderIf->codeMergeFlag( pcCU, uiAbsPartIdx ); } //! encode merge index Void TEncEntropy::encodeMergeIndex( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; assert( pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ); } m_pcEntropyCoderIf->codeMergeIndex( pcCU, uiAbsPartIdx ); } //! encode prediction mode Void TEncEntropy::encodePredMode( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } if ( pcCU->getSlice()->isIntra() ) { return; } m_pcEntropyCoderIf->codePredMode( pcCU, uiAbsPartIdx ); } //! encode split flag Void TEncEntropy::encodeSplitFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeSplitFlag( pcCU, uiAbsPartIdx, uiDepth ); } //! encode partition size Void TEncEntropy::encodePartSize( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codePartSize( pcCU, uiAbsPartIdx, uiDepth ); } /** Encode I_PCM information. * \param pcCU pointer to CU * \param uiAbsPartIdx CU index * \param bRD flag indicating estimation or encoding */ Void TEncEntropy::encodeIPCMInfo( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if(!pcCU->getSlice()->getSPS()->getUsePCM() || pcCU->getWidth(uiAbsPartIdx) > (1<getSlice()->getSPS()->getPCMLog2MaxSize()) || pcCU->getWidth(uiAbsPartIdx) < (1<getSlice()->getSPS()->getPCMLog2MinSize())) { return; } if( bRD ) { uiAbsPartIdx = 0; } m_pcEntropyCoderIf->codeIPCMInfo ( pcCU, uiAbsPartIdx ); } Void TEncEntropy::xEncodeTransform( Bool& bCodeDQP, Bool& codeChromaQpAdj, TComTU &rTu ) { //pcCU, absPartIdxCU, uiAbsPartIdx, uiDepth+1, uiTrIdx+1, quadrant, TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents(); const Bool bChroma = isChromaEnabled(pcCU->getPic()->getChromaFormat()); const UInt uiTrIdx = rTu.GetTransformDepthRel(); const UInt uiDepth = rTu.GetTransformDepthTotal(); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST const Bool bDebugRQT=pcCU->getSlice()->getFinalized() && DebugOptionList::DebugRQT.getInt()!=0; if (bDebugRQT) { printf("x..codeTransform: offsetLuma=%d offsetChroma=%d absPartIdx=%d, uiDepth=%d\n width=%d, height=%d, uiTrIdx=%d, uiInnerQuadIdx=%d\n", rTu.getCoefficientOffset(COMPONENT_Y), rTu.getCoefficientOffset(COMPONENT_Cb), uiAbsPartIdx, uiDepth, rTu.getRect(COMPONENT_Y).width, rTu.getRect(COMPONENT_Y).height, rTu.GetTransformDepthRel(), rTu.GetSectionNumber()); } #endif const UInt uiSubdiv = pcCU->getTransformIdx( uiAbsPartIdx ) > uiTrIdx;// + pcCU->getDepth( uiAbsPartIdx ) > uiDepth; const UInt uiLog2TrafoSize = rTu.GetLog2LumaTrSize(); UInt cbf[MAX_NUM_COMPONENT] = {0,0,0}; Bool bHaveACodedBlock = false; Bool bHaveACodedChromaBlock = false; for(UInt ch=0; chgetCbf( uiAbsPartIdx, compID , uiTrIdx ); if (cbf[ch] != 0) { bHaveACodedBlock = true; if (isChroma(compID)) { bHaveACodedChromaBlock = true; } } } if( pcCU->isIntra(uiAbsPartIdx) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_NxN && uiDepth == pcCU->getDepth(uiAbsPartIdx) ) { assert( uiSubdiv ); } else if( pcCU->isInter(uiAbsPartIdx) && (pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N) && uiDepth == pcCU->getDepth(uiAbsPartIdx) && (pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) ) { if ( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( uiSubdiv ); } else { assert(!uiSubdiv ); } } else if( uiLog2TrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { assert( uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { assert( !uiSubdiv ); } else if( uiLog2TrafoSize == pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( !uiSubdiv ); } else { assert( uiLog2TrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSubdiv, 5 - uiLog2TrafoSize ); } const UInt uiTrDepthCurr = uiDepth - pcCU->getDepth( uiAbsPartIdx ); const Bool bFirstCbfOfCU = uiTrDepthCurr == 0; for(UInt ch=COMPONENT_Cb; chgetCbf( uiAbsPartIdx, compID, uiTrDepthCurr - 1 ) ) { m_pcEntropyCoderIf->codeQtCbf( rTu, compID, (uiSubdiv == 0) ); } } else { assert( pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepthCurr ) == pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepthCurr - 1 ) ); } } if( uiSubdiv ) { TComTURecurse tuRecurseChild(rTu, true); do { xEncodeTransform( bCodeDQP, codeChromaQpAdj, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } else { { DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tTrIdx: abspart=" ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\tdepth=" ); DTRACE_CABAC_V( uiDepth ); DTRACE_CABAC_T( "\ttrdepth=" ); DTRACE_CABAC_V( pcCU->getTransformIdx( uiAbsPartIdx ) ); DTRACE_CABAC_T( "\n" ); } if( !pcCU->isIntra(uiAbsPartIdx) && uiDepth == pcCU->getDepth( uiAbsPartIdx ) && (!bChroma || (!pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cb, 0 ) && !pcCU->getCbf( uiAbsPartIdx, COMPONENT_Cr, 0 ) ) ) ) { assert( pcCU->getCbf( uiAbsPartIdx, COMPONENT_Y, 0 ) ); // printf( "saved one bin! " ); } else { m_pcEntropyCoderIf->codeQtCbf( rTu, COMPONENT_Y, true ); //luma CBF is always at the lowest level } if ( bHaveACodedBlock ) { // dQP: only for CTU once if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { if ( bCodeDQP ) { encodeQP( pcCU, rTu.GetAbsPartIdxCU() ); bCodeDQP = false; } } if ( pcCU->getSlice()->getUseChromaQpAdj() ) { if ( bHaveACodedChromaBlock && codeChromaQpAdj && !pcCU->getCUTransquantBypass(rTu.GetAbsPartIdxCU()) ) { encodeChromaQpAdjustment( pcCU, rTu.GetAbsPartIdxCU() ); codeChromaQpAdj = false; } } const UInt numValidComp=pcCU->getPic()->getNumberValidComponents(); for(UInt ch=COMPONENT_Y; chgetCbf(subTUIterator.GetAbsPartIdxTU(compID), compID, (uiTrIdx + 1)); if (subTUCBF != 0) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("Call NxN for chan %d width=%d height=%d cbf=%d\n", compID, subTUIterator.getRect(compID).width, subTUIterator.getRect(compID).height, 1); } #endif m_pcEntropyCoderIf->codeCoeffNxN( subTUIterator, (pcCU->getCoeff(compID) + subTUIterator.getCoefficientOffset(compID)), compID ); } } while (subTUIterator.nextSection(rTu)); } else { if (isChroma(compID) && (cbf[COMPONENT_Y] != 0)) { m_pcEntropyCoderIf->codeCrossComponentPrediction( rTu, compID ); } if (cbf[compID] != 0) { m_pcEntropyCoderIf->codeCoeffNxN( rTu, (pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID)), compID ); } } } } } } } //! encode intra direction for luma Void TEncEntropy::encodeIntraDirModeLuma ( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiplePU ) { m_pcEntropyCoderIf->codeIntraDirLumaAng( pcCU, absPartIdx , isMultiplePU); } //! encode intra direction for chroma Void TEncEntropy::encodeIntraDirModeChroma( TComDataCU* pcCU, UInt uiAbsPartIdx ) { m_pcEntropyCoderIf->codeIntraDirChroma( pcCU, uiAbsPartIdx ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPredEnabled && pcCU->getSlice()->getFinalized()) { UInt cdir=pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiAbsPartIdx); if (cdir==36) { cdir=pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx); } printf("coding chroma Intra dir: %d, uiAbsPartIdx: %d, luma dir: %d\n", cdir, uiAbsPartIdx, pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx)); } #endif } Void TEncEntropy::encodePredInfo( TComDataCU* pcCU, UInt uiAbsPartIdx ) { if( pcCU->isIntra( uiAbsPartIdx ) ) // If it is Intra mode, encode intra prediction mode. { encodeIntraDirModeLuma ( pcCU, uiAbsPartIdx,true ); if (pcCU->getPic()->getChromaFormat()!=CHROMA_400) { encodeIntraDirModeChroma( pcCU, uiAbsPartIdx ); if (enable4ChromaPUsInIntraNxNCU(pcCU->getPic()->getChromaFormat()) && pcCU->getPartitionSize( uiAbsPartIdx )==SIZE_NxN) { UInt uiPartOffset = ( pcCU->getPic()->getNumPartitionsInCtu() >> ( pcCU->getDepth(uiAbsPartIdx) << 1 ) ) >> 2; encodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset ); encodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset*2 ); encodeIntraDirModeChroma( pcCU, uiAbsPartIdx + uiPartOffset*3 ); } } } else // if it is Inter mode, encode motion vector and reference index { encodePUWise( pcCU, uiAbsPartIdx ); } } Void TEncEntropy::encodeCrossComponentPrediction( TComTU &rTu, ComponentID compID ) { m_pcEntropyCoderIf->codeCrossComponentPrediction( rTu, compID ); } //! encode motion information for every PU block Void TEncEntropy::encodePUWise( TComDataCU* pcCU, UInt uiAbsPartIdx ) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST const Bool bDebugPred = bDebugPredEnabled && pcCU->getSlice()->getFinalized(); #endif PartSize ePartSize = pcCU->getPartitionSize( uiAbsPartIdx ); UInt uiNumPU = ( ePartSize == SIZE_2Nx2N ? 1 : ( ePartSize == SIZE_NxN ? 4 : 2 ) ); UInt uiDepth = pcCU->getDepth( uiAbsPartIdx ); UInt uiPUOffset = ( g_auiPUOffset[UInt( ePartSize )] << ( ( pcCU->getSlice()->getSPS()->getMaxTotalCUDepth() - uiDepth ) << 1 ) ) >> 4; for ( UInt uiPartIdx = 0, uiSubPartIdx = uiAbsPartIdx; uiPartIdx < uiNumPU; uiPartIdx++, uiSubPartIdx += uiPUOffset ) { encodeMergeFlag( pcCU, uiSubPartIdx ); if ( pcCU->getMergeFlag( uiSubPartIdx ) ) { encodeMergeIndex( pcCU, uiSubPartIdx ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPred) { std::cout << "Coded merge flag, CU absPartIdx: " << uiAbsPartIdx << " PU(" << uiPartIdx << ") absPartIdx: " << uiSubPartIdx; std::cout << " merge index: " << (UInt)pcCU->getMergeIndex(uiSubPartIdx) << std::endl; } #endif } else { encodeInterDirPU( pcCU, uiSubPartIdx ); for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { if ( pcCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { encodeRefFrmIdxPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); encodeMvdPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); encodeMVPIdxPU ( pcCU, uiSubPartIdx, RefPicList( uiRefListIdx ) ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugPred) { std::cout << "refListIdx: " << uiRefListIdx << std::endl; std::cout << "MVD horizontal: " << pcCU->getCUMvField(RefPicList(uiRefListIdx))->getMvd( uiAbsPartIdx ).getHor() << std::endl; std::cout << "MVD vertical: " << pcCU->getCUMvField(RefPicList(uiRefListIdx))->getMvd( uiAbsPartIdx ).getVer() << std::endl; std::cout << "MVPIdxPU: " << pcCU->getMVPIdx(RefPicList( uiRefListIdx ), uiSubPartIdx) << std::endl; std::cout << "InterDir: " << (UInt)pcCU->getInterDir(uiSubPartIdx) << std::endl; } #endif } } } } return; } Void TEncEntropy::encodeInterDirPU( TComDataCU* pcCU, UInt uiAbsPartIdx ) { if ( !pcCU->getSlice()->isInterB() ) { return; } m_pcEntropyCoderIf->codeInterDir( pcCU, uiAbsPartIdx ); return; } //! encode reference frame index for a PU block Void TEncEntropy::encodeRefFrmIdxPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { assert( pcCU->isInter( uiAbsPartIdx ) ); if ( ( pcCU->getSlice()->getNumRefIdx( eRefList ) == 1 ) ) { return; } if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeRefFrmIdx( pcCU, uiAbsPartIdx, eRefList ); } return; } //! encode motion vector difference for a PU block Void TEncEntropy::encodeMvdPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { assert( pcCU->isInter( uiAbsPartIdx ) ); if ( pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList ) ) { m_pcEntropyCoderIf->codeMvd( pcCU, uiAbsPartIdx, eRefList ); } return; } Void TEncEntropy::encodeMVPIdxPU( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { if ( (pcCU->getInterDir( uiAbsPartIdx ) & ( 1 << eRefList )) ) { m_pcEntropyCoderIf->codeMVPIdx( pcCU, uiAbsPartIdx, eRefList ); } return; } Void TEncEntropy::encodeQtCbf( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) { m_pcEntropyCoderIf->codeQtCbf( rTu, compID, lowestLevel ); } Void TEncEntropy::encodeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ) { m_pcEntropyCoderIf->codeTransformSubdivFlag( uiSymbol, uiCtx ); } Void TEncEntropy::encodeQtRootCbf( TComDataCU* pcCU, UInt uiAbsPartIdx ) { m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); } Void TEncEntropy::encodeQtCbfZero( TComTU &rTu, const ChannelType chType ) { m_pcEntropyCoderIf->codeQtCbfZero( rTu, chType ); } Void TEncEntropy::encodeQtRootCbfZero( ) { m_pcEntropyCoderIf->codeQtRootCbfZero( ); } // dQP Void TEncEntropy::encodeQP( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD ) { if( bRD ) { uiAbsPartIdx = 0; } if ( pcCU->getSlice()->getPPS()->getUseDQP() ) { m_pcEntropyCoderIf->codeDeltaQP( pcCU, uiAbsPartIdx ); } } //! encode chroma qp adjustment Void TEncEntropy::encodeChromaQpAdjustment( TComDataCU* cu, UInt absPartIdx, Bool inRd ) { if( inRd ) { absPartIdx = 0; } m_pcEntropyCoderIf->codeChromaQpAdjustment( cu, absPartIdx ); } // texture //! encode coefficients Void TEncEntropy::encodeCoeff( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool& bCodeDQP, Bool& codeChromaQpAdj ) { #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST const Bool bDebugRQT=pcCU->getSlice()->getFinalized() && DebugOptionList::DebugRQT.getInt()!=0; #endif if( pcCU->isIntra(uiAbsPartIdx) ) { if (false) { DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tdecodeTransformIdx()\tCUDepth=" ) DTRACE_CABAC_V( uiDepth ) DTRACE_CABAC_T( "\n" ) } } else { if( !(pcCU->getMergeFlag( uiAbsPartIdx ) && pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N ) ) { m_pcEntropyCoderIf->codeQtRootCbf( pcCU, uiAbsPartIdx ); } if ( !pcCU->getQtRootCbf( uiAbsPartIdx ) ) { return; } } TComTURecurse tuRecurse(pcCU, uiAbsPartIdx, uiDepth); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (bDebugRQT) { printf("..codeCoeff: uiAbsPartIdx=%d, PU format=%d, 2Nx2N=%d, NxN=%d\n", uiAbsPartIdx, pcCU->getPartitionSize(uiAbsPartIdx), SIZE_2Nx2N, SIZE_NxN); } #endif xEncodeTransform( bCodeDQP, codeChromaQpAdj, tuRecurse ); } Void TEncEntropy::encodeCoeffNxN( TComTU &rTu, TCoeff* pcCoef, const ComponentID compID) { TComDataCU *pcCU = rTu.getCU(); if (pcCU->getCbf(rTu.GetAbsPartIdxTU(), compID, rTu.GetTransformDepthRel()) != 0) { if (rTu.getRect(compID).width != rTu.getRect(compID).height) { //code two sub-TUs TComTURecurse subTUIterator(rTu, false, TComTU::VERTICAL_SPLIT, true, compID); const UInt subTUSize = subTUIterator.getRect(compID).width * subTUIterator.getRect(compID).height; do { const UChar subTUCBF = pcCU->getCbf(subTUIterator.GetAbsPartIdxTU(compID), compID, (subTUIterator.GetTransformDepthRel() + 1)); if (subTUCBF != 0) { m_pcEntropyCoderIf->codeCoeffNxN( subTUIterator, (pcCoef + (subTUIterator.GetSectionNumber() * subTUSize)), compID); } } while (subTUIterator.nextSection(rTu)); } else { m_pcEntropyCoderIf->codeCoeffNxN(rTu, pcCoef, compID); } } } Void TEncEntropy::estimateBit (estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, const ChannelType chType, COEFF_SCAN_TYPE scanType ) { const UInt heightAtEntropyCoding = (width != height) ? (height >> 1) : height; m_pcEntropyCoderIf->estBit ( pcEstBitsSbac, width, heightAtEntropyCoding, chType, scanType ); } Int TEncEntropy::countNonZeroCoeffs( TCoeff* pcCoef, UInt uiSize ) { Int count = 0; for ( Int i = 0; i < uiSize; i++ ) { count += pcCoef[i] != 0; } return count; } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncEntropy.h000066400000000000000000000236031442026013100207700ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncEntropy.h \brief entropy encoder class (header) */ #ifndef __TENCENTROPY__ #define __TENCENTROPY__ #include "TLibCommon/TComSlice.h" #include "TLibCommon/TComDataCU.h" #include "TLibCommon/TComBitStream.h" #include "TLibCommon/ContextModel.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComTrQuant.h" #include "TLibCommon/TComSampleAdaptiveOffset.h" #include "TLibCommon/TComChromaFormat.h" class TEncSbac; class TEncCavlc; class SEI; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// entropy encoder pure class class TEncEntropyIf { public: virtual Void resetEntropy (const TComSlice *pSlice) = 0; virtual SliceType determineCabacInitIdx (const TComSlice *pSlice) = 0; virtual Void setBitstream ( TComBitIf* p ) = 0; virtual Void resetBits () = 0; virtual UInt getNumberOfWrittenBits() = 0; virtual Void codeVPS ( const TComVPS* pcVPS ) = 0; virtual Void codeSPS ( const TComSPS* pcSPS ) = 0; virtual Void codePPS ( const TComPPS* pcPPS ) = 0; virtual Void codeSliceHeader ( TComSlice* pcSlice ) = 0; virtual Void codeTilesWPPEntryPoint ( TComSlice* pSlice ) = 0; virtual Void codeTerminatingBit ( UInt uilsLast ) = 0; virtual Void codeSliceFinish () = 0; virtual Void codeMVPIdx ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) = 0; public: virtual Void codeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeMergeIndex ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void codePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0; virtual Void codePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ) = 0; virtual Void codeQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) = 0; virtual Void codeQtRootCbf ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeQtCbfZero ( TComTU &rTu, const ChannelType chType ) = 0; virtual Void codeQtRootCbfZero ( ) = 0; virtual Void codeIntraDirLumaAng( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool isMultiplePU ) = 0; virtual Void codeIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeInterDir ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeRefFrmIdx ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) = 0; virtual Void codeMvd ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) = 0; virtual Void codeCrossComponentPrediction( TComTU &rTu, ComponentID compID ) = 0; virtual Void codeDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx ) = 0; virtual Void codeCoeffNxN ( TComTU &rTu, TCoeff* pcCoef, const ComponentID compID ) = 0; virtual Void codeTransformSkipFlags ( TComTU &rTu, ComponentID component ) = 0; virtual Void codeSAOBlkParam (SAOBlkParam& saoBlkParam, const BitDepths &bitDepths, Bool* sliceEnabled, Bool leftMergeAvail, Bool aboveMergeAvail, Bool onlyEstMergeInfo = false) =0; virtual Void estBit (estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType, COEFF_SCAN_TYPE scanType) = 0; virtual Void codeExplicitRdpcmMode ( TComTU &rTu, const ComponentID compID ) = 0; virtual ~TEncEntropyIf() {} }; /// entropy encoder class class TEncEntropy { public: Void setEntropyCoder ( TEncEntropyIf* e ); Void setBitstream ( TComBitIf* p ) { m_pcEntropyCoderIf->setBitstream(p); } Void resetBits () { m_pcEntropyCoderIf->resetBits(); } UInt getNumberOfWrittenBits () { return m_pcEntropyCoderIf->getNumberOfWrittenBits(); } Void resetEntropy (const TComSlice *pSlice) { m_pcEntropyCoderIf->resetEntropy(pSlice); } SliceType determineCabacInitIdx (const TComSlice *pSlice) { return m_pcEntropyCoderIf->determineCabacInitIdx(pSlice); } Void encodeSliceHeader ( TComSlice* pcSlice ); Void encodeTilesWPPEntryPoint( TComSlice* pSlice ); Void encodeTerminatingBit ( UInt uiIsLast ); Void encodeSliceFinish (); TEncEntropyIf* m_pcEntropyCoderIf; public: Void encodeVPS ( const TComVPS* pcVPS); // SPS Void encodeSPS ( const TComSPS* pcSPS ); Void encodePPS ( const TComPPS* pcPPS ); Void encodeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD = false ); Void encodeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodeSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodePUWise ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void encodeInterDirPU ( TComDataCU* pcSubCU, UInt uiAbsPartIdx ); Void encodeRefFrmIdxPU ( TComDataCU* pcSubCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void encodeMvdPU ( TComDataCU* pcSubCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void encodeMVPIdxPU ( TComDataCU* pcSubCU, UInt uiAbsPartIdx, RefPicList eRefList ); Void encodeMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void encodeMergeIndex ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool bRD = false ); Void encodeIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodePredInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void encodeIntraDirModeLuma ( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiplePU = false ); Void encodeIntraDirModeChroma( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void encodeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ); Void encodeQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ); Void encodeQtCbfZero ( TComTU &rTu, const ChannelType chType ); Void encodeQtRootCbfZero ( ); Void encodeQtRootCbf ( TComDataCU* pcCU, UInt uiAbsPartIdx ); Void encodeQP ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodeChromaQpAdjustment ( TComDataCU* pcCU, UInt uiAbsPartIdx, Bool bRD = false ); Void encodeCrossComponentPrediction( TComTU &rTu, ComponentID compID ); private: Void xEncodeTransform ( Bool& bCodeDQP, Bool& codeChromaQpAdj, TComTU &rTu ); public: Void encodeCoeff ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Bool& bCodeDQP, Bool& codeChromaQpAdj ); Void encodeCoeffNxN ( TComTU &rTu, TCoeff* pcCoef, const ComponentID compID ); Void estimateBit ( estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType, COEFF_SCAN_TYPE scanType); Void encodeSAOBlkParam(SAOBlkParam& saoBlkParam, const BitDepths &bitDepths, Bool* sliceEnabled, Bool leftMergeAvail, Bool aboveMergeAvail){m_pcEntropyCoderIf->codeSAOBlkParam(saoBlkParam, bitDepths, sliceEnabled, leftMergeAvail, aboveMergeAvail, false);} static Int countNonZeroCoeffs( TCoeff* pcCoef, UInt uiSize ); };// END CLASS DEFINITION TEncEntropy //! \} #endif // __TENCENTROPY__ HM-HM-18.0/source/Lib/TLibEncoder/TEncGOP.cpp000066400000000000000000004016231442026013100203120ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncGOP.cpp \brief GOP encoder class */ #include #include #include #include #include "TEncTop.h" #include "TEncGOP.h" #include "TEncAnalyze.h" #include "libmd5/MD5.h" #include "TLibCommon/SEI.h" #include "TLibCommon/NAL.h" #include "NALwrite.h" #include #include #include using namespace std; //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== Int getLSB(Int poc, Int maxLSB) { if (poc >= 0) { return poc % maxLSB; } else { return (maxLSB - ((-poc) % maxLSB)) % maxLSB; } } TEncGOP::TEncGOP() { m_iLastIDR = 0; m_RASPOCforResetEncoder = MAX_INT; m_iGopSize = 0; m_iNumPicCoded = 0; //Niko m_bFirst = true; m_iLastRecoveryPicPOC = 0; m_pcCfg = NULL; m_pcSliceEncoder = NULL; m_pcListPic = NULL; m_pcEntropyCoder = NULL; m_pcCavlcCoder = NULL; m_pcSbacCoder = NULL; m_pcBinCABAC = NULL; m_bSeqFirst = true; m_bRefreshPending = 0; m_pocCRA = 0; m_numLongTermRefPicSPS = 0; ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps)); ::memset(m_ltRefPicUsedByCurrPicFlag, 0, sizeof(m_ltRefPicUsedByCurrPicFlag)); m_lastBPSEI = 0; m_bufferingPeriodSEIPresentInAU = false; m_associatedIRAPType = NAL_UNIT_CODED_SLICE_IDR_N_LP; m_associatedIRAPPOC = 0; m_pcDeblockingTempPicYuv = NULL; } TEncGOP::~TEncGOP() { } /** Create list to contain pointers to CTU start addresses of slice. */ Void TEncGOP::create() { m_bLongtermTestPictureHasBeenCoded = 0; m_bLongtermTestPictureHasBeenCoded2 = 0; } Void TEncGOP::destroy() { if (m_pcDeblockingTempPicYuv) { m_pcDeblockingTempPicYuv->destroy(); delete m_pcDeblockingTempPicYuv; m_pcDeblockingTempPicYuv = NULL; } #if JVET_X0048_X0103_FILM_GRAIN if (m_pcCfg->getFilmGrainAnalysisEnabled()) { m_FGAnalyser.destroy(); } #endif } Void TEncGOP::init ( TEncTop* pcTEncTop ) { m_pcEncTop = pcTEncTop; m_pcCfg = pcTEncTop; m_seiEncoder.init(m_pcCfg, pcTEncTop, this); m_pcSliceEncoder = pcTEncTop->getSliceEncoder(); m_pcListPic = pcTEncTop->getListPic(); m_pcEntropyCoder = pcTEncTop->getEntropyCoder(); m_pcCavlcCoder = pcTEncTop->getCavlcCoder(); m_pcSbacCoder = pcTEncTop->getSbacCoder(); m_pcBinCABAC = pcTEncTop->getBinCABAC(); m_pcLoopFilter = pcTEncTop->getLoopFilter(); m_pcSAO = pcTEncTop->getSAO(); m_pcRateCtrl = pcTEncTop->getRateCtrl(); m_lastBPSEI = 0; m_totalCoded = 0; #if JVET_X0048_X0103_FILM_GRAIN if (m_pcCfg->getFilmGrainAnalysisEnabled()) { m_FGAnalyser.init(m_pcCfg->getSourceWidth(), m_pcCfg->getSourceHeight(), m_pcCfg->getSourcePadding(0), m_pcCfg->getSourcePadding(1), IPCOLOURSPACE_UNCHANGED, false, m_pcCfg->getChromaFormatIdc(), *(BitDepths*)m_pcCfg->getBitDepthInput(), *(BitDepths*)m_pcCfg->getBitDepth(), m_pcCfg->getFrameSkip(), m_pcCfg->getFGCSEICompModelPresent(), m_pcCfg->getFilmGrainExternalMask(), m_pcCfg->getFilmGrainExternalDenoised()); } #endif } #if MCTS_EXTRACTION Void TEncGOP::generateVPS_RBSP(TComBitIf* rbsp, const TComVPS *vps) { m_pcEntropyCoder->setBitstream(rbsp); m_pcEntropyCoder->encodeVPS(vps); } Void TEncGOP::generateSPS_RBSP(TComBitIf* rbsp, const TComSPS *sps) { m_pcEntropyCoder->setBitstream(rbsp); m_pcEntropyCoder->encodeSPS(sps); } Void TEncGOP::generatePPS_RBSP(TComBitIf* rbsp, const TComPPS *pps) { m_pcEntropyCoder->setBitstream(rbsp); m_pcEntropyCoder->encodePPS(pps); } #endif Int TEncGOP::xWriteVPS (AccessUnit &accessUnit, const TComVPS *vps) { OutputNALUnit nalu(NAL_UNIT_VPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodeVPS(vps); accessUnit.push_back(new NALUnitEBSP(nalu)); return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; } Int TEncGOP::xWriteSPS (AccessUnit &accessUnit, const TComSPS *sps) { OutputNALUnit nalu(NAL_UNIT_SPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodeSPS(sps); accessUnit.push_back(new NALUnitEBSP(nalu)); return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; } Int TEncGOP::xWritePPS (AccessUnit &accessUnit, const TComPPS *pps) { OutputNALUnit nalu(NAL_UNIT_PPS); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodePPS(pps); accessUnit.push_back(new NALUnitEBSP(nalu)); return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8; } Int TEncGOP::xWriteParameterSets (AccessUnit &accessUnit, TComSlice *slice, const Bool bSeqFirst) { Int actualTotalBits = 0; if (bSeqFirst) { actualTotalBits += xWriteVPS(accessUnit, m_pcEncTop->getVPS()); } if (m_pcEncTop->SPSNeedsWriting(slice->getSPS()->getSPSId())) // Note this assumes that all changes to the SPS are made at the TEncTop level prior to picture creation (TEncTop::xGetNewPicBuffer). { assert(bSeqFirst); // Implementations that use more than 1 SPS need to be aware of activation issues. actualTotalBits += xWriteSPS(accessUnit, slice->getSPS()); } if (m_pcEncTop->PPSNeedsWriting(slice->getPPS()->getPPSId())) // Note this assumes that all changes to the PPS are made at the TEncTop level prior to picture creation (TEncTop::xGetNewPicBuffer). { actualTotalBits += xWritePPS(accessUnit, slice->getPPS()); } return actualTotalBits; } Void TEncGOP::xWriteAccessUnitDelimiter (AccessUnit &accessUnit, TComSlice *slice) { AUDWriter audWriter; OutputNALUnit nalu(NAL_UNIT_ACCESS_UNIT_DELIMITER); Int picType = slice->isIntra() ? 0 : (slice->isInterP() ? 1 : 2); audWriter.codeAUD(nalu.m_Bitstream, picType); accessUnit.push_front(new NALUnitEBSP(nalu)); } // write SEI list into one NAL unit and add it to the Access unit at auPos Void TEncGOP::xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps) { // don't do anything, if we get an empty list if (seiMessages.empty()) { return; } OutputNALUnit nalu(naluType, temporalId); m_seiWriter.writeSEImessages(nalu.m_Bitstream, seiMessages, sps, false); auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu)); auPos++; } Void TEncGOP::xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps) { // don't do anything, if we get an empty list if (seiMessages.empty()) { return; } for (SEIMessages::const_iterator sei = seiMessages.begin(); sei!=seiMessages.end(); sei++ ) { SEIMessages tmpMessages; tmpMessages.push_back(*sei); OutputNALUnit nalu(naluType, temporalId); m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, sps, false); auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu)); auPos++; } } Void TEncGOP::xClearSEIs(SEIMessages& seiMessages, Bool deleteMessages) { if (deleteMessages) { deleteSEIs(seiMessages); } else { seiMessages.clear(); } } // write SEI messages as separate NAL units ordered Void TEncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, Bool testWrite) { AccessUnit::iterator itNalu = accessUnit.begin(); while ( (itNalu!=accessUnit.end())&& ( (*itNalu)->m_nalUnitType==NAL_UNIT_ACCESS_UNIT_DELIMITER || (*itNalu)->m_nalUnitType==NAL_UNIT_VPS || (*itNalu)->m_nalUnitType==NAL_UNIT_SPS || (*itNalu)->m_nalUnitType==NAL_UNIT_PPS )) { itNalu++; } SEIMessages localMessages = seiMessages; SEIMessages currentMessages; #if ENC_DEC_TRACE g_HLSTraceEnable = !testWrite; #endif // The case that a specific SEI is not present is handled in xWriteSEI (empty list) #if JCTVC_AD0021_SEI_MANIFEST // When SEI Manifest SEI message is present in an SEI NAL unit, the SEI Manifest SEI message shall be the first SEI message in the SEI NAL unit (D3.45 in ISO/IEC 23008-2). if (m_pcCfg->getSEIManifestSEIEnabled()) { currentMessages = extractSeisByType(localMessages, SEI::SEI_MANIFEST); assert(currentMessages.size() <= 1); xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION // When SEI Manifest SEI message is present in an SEI NAL unit, the SEI Manifest SEI message shall be the first SEI message in the SEI NAL unit (D3.45 in ISO/IEC 23008-2). if (m_pcCfg->getSEIPrefixIndicationSEIEnabled()) { currentMessages = extractSeisByType(localMessages, SEI::SEI_PREFIX_INDICATION); xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); } #endif // Active parameter sets SEI must always be the first SEI currentMessages = extractSeisByType(localMessages, SEI::ACTIVE_PARAMETER_SETS); assert (currentMessages.size() <= 1); xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); // Buffering period SEI must always be following active parameter sets currentMessages = extractSeisByType(localMessages, SEI::BUFFERING_PERIOD); assert (currentMessages.size() <= 1); xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); // Picture timing SEI must always be following buffering period currentMessages = extractSeisByType(localMessages, SEI::PICTURE_TIMING); assert (currentMessages.size() <= 1); xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); // Decoding unit info SEI must always be following picture timing if (!duInfoSeiMessages.empty()) { currentMessages.push_back(duInfoSeiMessages.front()); if (!testWrite) { duInfoSeiMessages.pop_front(); } xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); } // Scalable nesting SEI must always be the following DU info currentMessages = extractSeisByType(localMessages, SEI::SCALABLE_NESTING); xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(currentMessages, !testWrite); // And finally everything else one by one xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, localMessages, accessUnit, itNalu, temporalId, sps); xClearSEIs(localMessages, !testWrite); if (!testWrite) { seiMessages.clear(); } } Void TEncGOP::xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque &duData) { AccessUnit testAU; SEIMessages picTimingSEIs = getSeisByType(seiMessages, SEI::PICTURE_TIMING); assert (picTimingSEIs.size() < 2); SEIPictureTiming * picTiming = picTimingSEIs.empty() ? NULL : (SEIPictureTiming*) picTimingSEIs.front(); // test writing xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, testAU, temporalId, sps, true); // update Timing and DU info SEI xUpdateDuData(testAU, duData); xUpdateTimingSEI(picTiming, duData, sps); xUpdateDuInfoSEI(duInfoSeiMessages, picTiming); // actual writing xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, accessUnit, temporalId, sps, false); // testAU will automatically be cleaned up when losing scope } Void TEncGOP::xWriteTrailingSEIMessages (SEIMessages& seiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps) { // Note: using accessUnit.end() works only as long as this function is called after slice coding and before EOS/EOB NAL units AccessUnit::iterator pos = accessUnit.end(); xWriteSEISeparately(NAL_UNIT_SUFFIX_SEI, seiMessages, accessUnit, pos, temporalId, sps); deleteSEIs(seiMessages); } Void TEncGOP::xWriteDuSEIMessages (SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque &duData) { const TComHRD *hrd = sps->getVuiParameters()->getHrdParameters(); if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && hrd->getSubPicCpbParamsPresentFlag() ) { Int naluIdx = 0; AccessUnit::iterator nalu = accessUnit.begin(); // skip over first DU, we have a DU info SEI there already while (naluIdx < duData[0].accumNalsDU && nalu!=accessUnit.end()) { naluIdx++; nalu++; } SEIMessages::iterator duSEI = duInfoSeiMessages.begin(); // loop over remaining DUs for (Int duIdx = 1; duIdx < duData.size(); duIdx++) { if (duSEI == duInfoSeiMessages.end()) { // if the number of generated SEIs matches the number of DUs, this should not happen assert (false); return; } // write the next SEI SEIMessages tmpSEI; tmpSEI.push_back(*duSEI); xWriteSEI(NAL_UNIT_PREFIX_SEI, tmpSEI, accessUnit, nalu, temporalId, sps); // nalu points to the position after the SEI, so we have to increase the index as well naluIdx++; while ((naluIdx < duData[duIdx].accumNalsDU) && nalu!=accessUnit.end()) { naluIdx++; nalu++; } duSEI++; } } deleteSEIs(duInfoSeiMessages); } #if MCTS_EXTRACTION Void TEncGOP::xCreateIRAPLeadingSEIMessages(SEIMessages& seiMessages, const TComVPS *vps, const TComSPS *sps, const TComPPS *pps) #else Void TEncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const TComSPS *sps, const TComPPS *pps) #endif { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); if(m_pcCfg->getActiveParameterSetsSEIEnabled()) { SEIActiveParameterSets *sei = new SEIActiveParameterSets; m_seiEncoder.initSEIActiveParameterSets (sei, m_pcCfg->getVPS(), sps); seiMessages.push_back(sei); } if(m_pcCfg->getFramePackingArrangementSEIEnabled()) { SEIFramePacking *sei = new SEIFramePacking; m_seiEncoder.initSEIFramePacking (sei, m_iNumPicCoded); seiMessages.push_back(sei); } if(m_pcCfg->getSegmentedRectFramePackingArrangementSEIEnabled()) { SEISegmentedRectFramePacking *sei = new SEISegmentedRectFramePacking; m_seiEncoder.initSEISegmentedRectFramePacking(sei); seiMessages.push_back(sei); } if (m_pcCfg->getDisplayOrientationSEIAngle()) { SEIDisplayOrientation *sei = new SEIDisplayOrientation; m_seiEncoder.initSEIDisplayOrientation(sei); seiMessages.push_back(sei); } if(m_pcCfg->getToneMappingInfoSEIEnabled()) { SEIToneMappingInfo *sei = new SEIToneMappingInfo; m_seiEncoder.initSEIToneMappingInfo (sei); seiMessages.push_back(sei); } if(m_pcCfg->getTMCTSSEIEnabled()) { SEITempMotionConstrainedTileSets *sei = new SEITempMotionConstrainedTileSets; m_seiEncoder.initSEITempMotionConstrainedTileSets(sei, pps); seiMessages.push_back(sei); } #if MCTS_EXTRACTION if (m_pcCfg->getTMCTSExtractionSEIEnabled()) { SEIMCTSExtractionInfoSet *sei = new SEIMCTSExtractionInfoSet; m_seiEncoder.initSEIMCTSExtractionInfo(sei, vps, sps, pps); seiMessages.push_back(sei); } #endif if(m_pcCfg->getTimeCodeSEIEnabled()) { SEITimeCode *seiTimeCode = new SEITimeCode; m_seiEncoder.initSEITimeCode(seiTimeCode); seiMessages.push_back(seiTimeCode); } if(m_pcCfg->getKneeSEIEnabled()) { SEIKneeFunctionInfo *sei = new SEIKneeFunctionInfo; m_seiEncoder.initSEIKneeFunctionInfo(sei); seiMessages.push_back(sei); } if (m_pcCfg->getCcvSEIEnabled()) { SEIContentColourVolume *seiContentColourVolume = new SEIContentColourVolume; m_seiEncoder.initSEIContentColourVolume(seiContentColourVolume); seiMessages.push_back(seiContentColourVolume); } #if SHUTTER_INTERVAL_SEI_MESSAGE if (m_pcCfg->getSiiSEIEnabled()) { SEIShutterIntervalInfo *seiShutterInterval = new SEIShutterIntervalInfo; m_seiEncoder.initSEIShutterIntervalInfo(seiShutterInterval); seiMessages.push_back(seiShutterInterval); } #endif #if SEI_ENCODER_CONTROL #if JVET_X0048_X0103_FILM_GRAIN if (m_pcCfg->getFilmGrainCharactersticsSEIEnabled() && !m_pcCfg->getFilmGrainCharactersticsSEIPerPictureSEI()) { SEIFilmGrainCharacteristics* seiFGC = new SEIFilmGrainCharacteristics; m_seiEncoder.initSEIFilmGrainCharacteristics(seiFGC); if (m_pcCfg->getFilmGrainAnalysisEnabled()) { seiFGC->m_log2ScaleFactor = m_FGAnalyser.getLog2scaleFactor(); for (int compIdx = 0; compIdx < getNumberValidComponents(m_pcCfg->getChromaFormatIdc()); compIdx++) { if (seiFGC->m_compModel[compIdx].bPresentFlag) { // higher importance of presentFlag is from cfg file seiFGC->m_compModel[compIdx] = m_FGAnalyser.getCompModel(compIdx); } } } seiMessages.push_back(seiFGC); } #else // film grain if (m_pcCfg->getFilmGrainCharactersticsSEIEnabled()) { SEIFilmGrainCharacteristics *seiFGC = new SEIFilmGrainCharacteristics; m_seiEncoder.initSEIFilmGrainCharacteristics(seiFGC); seiMessages.push_back(seiFGC); } #endif // content light level if (m_pcCfg->getCLLSEIEnabled()) { SEIContentLightLevelInfo *seiCLL = new SEIContentLightLevelInfo; m_seiEncoder.initSEIContentLightLevel(seiCLL); seiMessages.push_back(seiCLL); } // ambient viewing environment if (m_pcCfg->getAmbientViewingEnvironmentSEIEnabled()) { SEIAmbientViewingEnvironment *seiAVE = new SEIAmbientViewingEnvironment; m_seiEncoder.initSEIAmbientViewingEnvironment(seiAVE); seiMessages.push_back(seiAVE); } #endif if (m_pcCfg->getErpSEIEnabled()) { SEIEquirectangularProjection *sei = new SEIEquirectangularProjection; m_seiEncoder.initSEIErp(sei); seiMessages.push_back(sei); } if (m_pcCfg->getSphereRotationSEIEnabled()) { SEISphereRotation *sei = new SEISphereRotation; m_seiEncoder.initSEISphereRotation(sei); seiMessages.push_back(sei); } if (m_pcCfg->getOmniViewportSEIEnabled()) { SEIOmniViewport *sei = new SEIOmniViewport; m_seiEncoder.initSEIOmniViewport(sei); seiMessages.push_back(sei); } if (m_pcCfg->getCmpSEIEnabled()) { SEICubemapProjection *seiCubemapProjection = new SEICubemapProjection; m_seiEncoder.initSEICubemapProjection(seiCubemapProjection); seiMessages.push_back(seiCubemapProjection); } if (m_pcCfg->getRwpSEIEnabled()) { SEIRegionWisePacking *seiRegionWisePacking = new SEIRegionWisePacking; m_seiEncoder.initSEIRegionWisePacking(seiRegionWisePacking); seiMessages.push_back(seiRegionWisePacking); } if (m_pcCfg->getFviSEIEnabled()) { SEIFisheyeVideoInfo *sei = new SEIFisheyeVideoInfo; m_seiEncoder.initSEIFisheyeVideoInfo(sei); seiMessages.push_back(sei); } if(m_pcCfg->getMasteringDisplaySEI().colourVolumeSEIEnabled) { const TComSEIMasteringDisplay &seiCfg=m_pcCfg->getMasteringDisplaySEI(); SEIMasteringDisplayColourVolume *sei = new SEIMasteringDisplayColourVolume; sei->values = seiCfg; seiMessages.push_back(sei); } if(m_pcCfg->getChromaResamplingFilterHintEnabled()) { SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint = new SEIChromaResamplingFilterHint; m_seiEncoder.initSEIChromaResamplingFilterHint(seiChromaResamplingFilterHint, m_pcCfg->getChromaResamplingHorFilterIdc(), m_pcCfg->getChromaResamplingVerFilterIdc()); seiMessages.push_back(seiChromaResamplingFilterHint); } if(m_pcCfg->getSEIAlternativeTransferCharacteristicsSEIEnable()) { SEIAlternativeTransferCharacteristics *seiAlternativeTransferCharacteristics = new SEIAlternativeTransferCharacteristics; m_seiEncoder.initSEIAlternativeTransferCharacteristics(seiAlternativeTransferCharacteristics); seiMessages.push_back(seiAlternativeTransferCharacteristics); } } Void TEncGOP::xCreatePerPictureSEIMessages (Int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, TComSlice *slice) { if( ( m_pcCfg->getBufferingPeriodSEIEnabled() ) && ( slice->getSliceType() == I_SLICE ) && ( slice->getSPS()->getVuiParametersPresentFlag() ) && ( ( slice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( slice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { SEIBufferingPeriod *bufferingPeriodSEI = new SEIBufferingPeriod(); m_seiEncoder.initSEIBufferingPeriod(bufferingPeriodSEI, slice); seiMessages.push_back(bufferingPeriodSEI); m_bufferingPeriodSEIPresentInAU = true; if (m_pcCfg->getScalableNestingSEIEnabled()) { SEIBufferingPeriod *bufferingPeriodSEIcopy = new SEIBufferingPeriod(); bufferingPeriodSEI->copyTo(*bufferingPeriodSEIcopy); nestedSeiMessages.push_back(bufferingPeriodSEIcopy); } } if (picInGOP ==0 && m_pcCfg->getSOPDescriptionSEIEnabled() ) // write SOP description SEI (if enabled) at the beginning of GOP { SEISOPDescription* sopDescriptionSEI = new SEISOPDescription(); m_seiEncoder.initSEISOPDescription(sopDescriptionSEI, slice, picInGOP, m_iLastIDR, m_iGopSize); seiMessages.push_back(sopDescriptionSEI); } if( ( m_pcEncTop->getRecoveryPointSEIEnabled() ) && ( slice->getSliceType() == I_SLICE ) ) { if( m_pcEncTop->getGradualDecodingRefreshInfoEnabled() && !slice->getRapPicFlag() ) { // Gradual decoding refresh SEI SEIRegionRefreshInfo *gradualDecodingRefreshInfoSEI = new SEIRegionRefreshInfo(); gradualDecodingRefreshInfoSEI->m_gdrForegroundFlag = true; // Indicating all "foreground" seiMessages.push_back(gradualDecodingRefreshInfoSEI); } // Recovery point SEI SEIRecoveryPoint *recoveryPointSEI = new SEIRecoveryPoint(); m_seiEncoder.initSEIRecoveryPoint(recoveryPointSEI, slice); seiMessages.push_back(recoveryPointSEI); } if (m_pcCfg->getTemporalLevel0IndexSEIEnabled()) { SEITemporalLevel0Index *temporalLevel0IndexSEI = new SEITemporalLevel0Index(); m_seiEncoder.initTemporalLevel0IndexSEI(temporalLevel0IndexSEI, slice); seiMessages.push_back(temporalLevel0IndexSEI); } if( m_pcEncTop->getNoDisplaySEITLayer() && ( slice->getTLayer() >= m_pcEncTop->getNoDisplaySEITLayer() ) ) { SEINoDisplay *seiNoDisplay = new SEINoDisplay; seiNoDisplay->m_noDisplay = true; seiMessages.push_back(seiNoDisplay); } // insert one Colour Remapping Info SEI for the picture (if the file exists) if (!m_pcCfg->getColourRemapInfoSEIFileRoot().empty()) { SEIColourRemappingInfo *seiColourRemappingInfo = new SEIColourRemappingInfo(); const Bool success = m_seiEncoder.initSEIColourRemappingInfo(seiColourRemappingInfo, slice->getPOC() ); if(success) { seiMessages.push_back(seiColourRemappingInfo); } else { delete seiColourRemappingInfo; } } // insert one Annotated Region SEI for the picture (if the file exists) if (!m_pcCfg->getAnnotatedRegionSEIFileRoot().empty()) { SEIAnnotatedRegions *seiAnnotatedRegions = new SEIAnnotatedRegions(); const Bool success = m_seiEncoder.initSEIAnnotatedRegions(seiAnnotatedRegions, slice->getPOC()); if (success) { seiMessages.push_back(seiAnnotatedRegions); } else { delete seiAnnotatedRegions; } } // insert one Regional Nesting SEI for the picture (if the file exists) if (!m_pcCfg->getRegionalNestingSEIFileRoot().empty()) { SEIRegionalNesting *seiRegionalNesting= new SEIRegionalNesting(); const Bool success = m_seiEncoder.initSEIRegionalNesting(seiRegionalNesting, slice->getPOC() ); if(success) { seiMessages.push_back(seiRegionalNesting); } else { delete seiRegionalNesting; } } #if JVET_X0048_X0103_FILM_GRAIN // Film Grain Characteristics SEI insertion at at frame level if (m_pcCfg->getFilmGrainCharactersticsSEIEnabled() && m_pcCfg->getFilmGrainCharactersticsSEIPerPictureSEI()) { SEIFilmGrainCharacteristics* fgcSEI = new SEIFilmGrainCharacteristics; m_seiEncoder.initSEIFilmGrainCharacteristics(fgcSEI); if (m_pcCfg->getFilmGrainAnalysisEnabled()) { fgcSEI->m_log2ScaleFactor = m_FGAnalyser.getLog2scaleFactor(); for (int compIdx = 0; compIdx < getNumberValidComponents(m_pcCfg->getChromaFormatIdc()); compIdx++) { if (fgcSEI->m_compModel[compIdx].bPresentFlag) { // higher importance of presentFlag is from cfg file fgcSEI->m_compModel[compIdx] = m_FGAnalyser.getCompModel(compIdx); } } } seiMessages.push_back(fgcSEI); } #endif #if JCTVC_AD0021_SEI_MANIFEST // Make sure that sei_manifest and sei_prefix are the last two initialized sei_msg, otherwise it will cause these two // Sei messages to not be able to enter all SEI messages if (m_pcCfg->getSEIManifestSEIEnabled()) { SEIManifest* seiSEIManifest = new SEIManifest; m_seiEncoder.initSEISEIManifest(seiSEIManifest, seiMessages); seiMessages.push_back(seiSEIManifest); } #endif #if JCTVC_AD0021_SEI_PREFIX_INDICATION if (m_pcCfg->getSEIPrefixIndicationSEIEnabled()) { int NumOfSEIPrefixMsg = 0; for (auto& it : seiMessages) { if (it->payloadType() == SEI::SEI_MANIFEST) { break; } NumOfSEIPrefixMsg++; } for (auto& it : seiMessages) { if (NumOfSEIPrefixMsg == 0 || it->payloadType() == SEI::SEI_MANIFEST) { break; } SEIPrefixIndication* seiSEIPrefixIndication = new SEIPrefixIndication; m_seiEncoder.initSEISEIPrefixIndication(seiSEIPrefixIndication, it); seiMessages.push_back(seiSEIPrefixIndication); NumOfSEIPrefixMsg--; } } #endif } Void TEncGOP::xCreateScalableNestingSEI (SEIMessages& seiMessages, SEIMessages& nestedSeiMessages) { SEIMessages tmpMessages; while (!nestedSeiMessages.empty()) { SEI* sei=nestedSeiMessages.front(); nestedSeiMessages.pop_front(); tmpMessages.push_back(sei); SEIScalableNesting *nestingSEI = new SEIScalableNesting(); m_seiEncoder.initSEIScalableNesting(nestingSEI, tmpMessages); seiMessages.push_back(nestingSEI); tmpMessages.clear(); } } Void TEncGOP::xCreatePictureTimingSEI (Int IRAPGOPid, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, SEIMessages& duInfoSeiMessages, TComSlice *slice, Bool isField, std::deque &duData) { const TComVUI *vui = slice->getSPS()->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); // update decoding unit parameters if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( slice->getSPS()->getVuiParametersPresentFlag() ) && ( hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) ) { Int picSptDpbOutputDuDelay = 0; SEIPictureTiming *pictureTimingSEI = new SEIPictureTiming(); // DU parameters if( hrd->getSubPicCpbParamsPresentFlag() ) { UInt numDU = (UInt) duData.size(); pictureTimingSEI->m_numDecodingUnitsMinus1 = ( numDU - 1 ); pictureTimingSEI->m_duCommonCpbRemovalDelayFlag = false; pictureTimingSEI->m_numNalusInDuMinus1.resize( numDU ); pictureTimingSEI->m_duCpbRemovalDelayMinus1.resize( numDU ); } pictureTimingSEI->m_auCpbRemovalDelay = std::min(std::max(1, m_totalCoded - m_lastBPSEI), static_cast(pow(2, static_cast(hrd->getCpbRemovalDelayLengthMinus1()+1)))); // Syntax element signalled as minus, hence the . pictureTimingSEI->m_picDpbOutputDelay = slice->getSPS()->getNumReorderPics(slice->getSPS()->getMaxTLayers()-1) + slice->getPOC() - m_totalCoded; if(m_pcCfg->getEfficientFieldIRAPEnabled() && IRAPGOPid > 0 && IRAPGOPid < m_iGopSize) { // if pictures have been swapped there is likely one more picture delay on their tid. Very rough approximation pictureTimingSEI->m_picDpbOutputDelay ++; } Int factor = hrd->getTickDivisorMinus2() + 2; pictureTimingSEI->m_picDpbOutputDuDelay = factor * pictureTimingSEI->m_picDpbOutputDelay; if( m_pcCfg->getDecodingUnitInfoSEIEnabled() ) { picSptDpbOutputDuDelay = factor * pictureTimingSEI->m_picDpbOutputDelay; } if (m_bufferingPeriodSEIPresentInAU) { m_lastBPSEI = m_totalCoded; } if( hrd->getSubPicCpbParamsPresentFlag() ) { Int i; UInt64 ui64Tmp; UInt uiPrev = 0; UInt numDU = ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 ); std::vector &rDuCpbRemovalDelayMinus1 = pictureTimingSEI->m_duCpbRemovalDelayMinus1; UInt maxDiff = ( hrd->getTickDivisorMinus2() + 2 ) - 1; for( i = 0; i < numDU; i ++ ) { pictureTimingSEI->m_numNalusInDuMinus1[ i ] = ( i == 0 ) ? ( duData[i].accumNalsDU - 1 ) : ( duData[i].accumNalsDU- duData[i-1].accumNalsDU - 1 ); } if( numDU == 1 ) { rDuCpbRemovalDelayMinus1[ 0 ] = 0; /* don't care */ } else { rDuCpbRemovalDelayMinus1[ numDU - 1 ] = 0;/* by definition */ UInt tmp = 0; UInt accum = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { tmp ++; } } uiPrev = 0; UInt flag = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { flag = 0; ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { if(uiPrev >= maxDiff - tmp) { ui64Tmp = uiPrev + 1; flag = 1; } else ui64Tmp = maxDiff - tmp + 1; } rDuCpbRemovalDelayMinus1[ i ] = (UInt)ui64Tmp - uiPrev - 1; if( (Int)rDuCpbRemovalDelayMinus1[ i ] < 0 ) { rDuCpbRemovalDelayMinus1[ i ] = 0; } else if (tmp > 0 && flag == 1) { tmp --; } accum += rDuCpbRemovalDelayMinus1[ i ] + 1; uiPrev = accum; } } } if( m_pcCfg->getPictureTimingSEIEnabled() ) { pictureTimingSEI->m_picStruct = (isField && slice->getPic()->isTopField())? 1 : isField? 2 : 0; seiMessages.push_back(pictureTimingSEI); if ( m_pcCfg->getScalableNestingSEIEnabled() ) // put picture timing SEI into scalable nesting SEI { SEIPictureTiming *pictureTimingSEIcopy = new SEIPictureTiming(); pictureTimingSEI->copyTo(*pictureTimingSEIcopy); nestedSeiMessages.push_back(pictureTimingSEIcopy); } } if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && hrd->getSubPicCpbParamsPresentFlag() ) { for( Int i = 0; i < ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 ); i ++ ) { SEIDecodingUnitInfo *duInfoSEI = new SEIDecodingUnitInfo(); duInfoSEI->m_decodingUnitIdx = i; duInfoSEI->m_duSptCpbRemovalDelay = pictureTimingSEI->m_duCpbRemovalDelayMinus1[i] + 1; duInfoSEI->m_dpbOutputDuDelayPresentFlag = false; duInfoSEI->m_picSptDpbOutputDuDelay = picSptDpbOutputDuDelay; duInfoSeiMessages.push_back(duInfoSEI); } } if( !m_pcCfg->getPictureTimingSEIEnabled() && pictureTimingSEI ) { delete pictureTimingSEI; } } } Void TEncGOP::xUpdateDuData(AccessUnit &testAU, std::deque &duData) { if (duData.empty()) { return; } // fix first UInt numNalUnits = (UInt)testAU.size(); UInt numRBSPBytes = 0; for (AccessUnit::const_iterator it = testAU.begin(); it != testAU.end(); it++) { numRBSPBytes += UInt((*it)->m_nalUnitData.str().size()); } duData[0].accumBitsDU += ( numRBSPBytes << 3 ); duData[0].accumNalsDU += numNalUnits; // adapt cumulative sums for all following DUs // and add one DU info SEI, if enabled for (Int i=1; igetDecodingUnitInfoSEIEnabled()) { numNalUnits += 1; numRBSPBytes += ( 5 << 3 ); } duData[i].accumBitsDU += numRBSPBytes; // probably around 5 bytes duData[i].accumNalsDU += numNalUnits; } // The last DU may have a trailing SEI if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE) { duData.back().accumBitsDU += ( 20 << 3 ); // probably around 20 bytes - should be further adjusted, e.g. by type duData.back().accumNalsDU += 1; } } Void TEncGOP::xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque &duData, const TComSPS *sps) { if (!pictureTimingSEI) { return; } const TComVUI *vui = sps->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); if( hrd->getSubPicCpbParamsPresentFlag() ) { Int i; UInt64 ui64Tmp; UInt uiPrev = 0; UInt numDU = ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 ); std::vector &rDuCpbRemovalDelayMinus1 = pictureTimingSEI->m_duCpbRemovalDelayMinus1; UInt maxDiff = ( hrd->getTickDivisorMinus2() + 2 ) - 1; for( i = 0; i < numDU; i ++ ) { pictureTimingSEI->m_numNalusInDuMinus1[ i ] = ( i == 0 ) ? ( duData[i].accumNalsDU - 1 ) : ( duData[i].accumNalsDU- duData[i-1].accumNalsDU - 1 ); } if( numDU == 1 ) { rDuCpbRemovalDelayMinus1[ 0 ] = 0; /* don't care */ } else { rDuCpbRemovalDelayMinus1[ numDU - 1 ] = 0;/* by definition */ UInt tmp = 0; UInt accum = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { tmp ++; } } uiPrev = 0; UInt flag = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { flag = 0; ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { if(uiPrev >= maxDiff - tmp) { ui64Tmp = uiPrev + 1; flag = 1; } else ui64Tmp = maxDiff - tmp + 1; } rDuCpbRemovalDelayMinus1[ i ] = (UInt)ui64Tmp - uiPrev - 1; if( (Int)rDuCpbRemovalDelayMinus1[ i ] < 0 ) { rDuCpbRemovalDelayMinus1[ i ] = 0; } else if (tmp > 0 && flag == 1) { tmp --; } accum += rDuCpbRemovalDelayMinus1[ i ] + 1; uiPrev = accum; } } } } Void TEncGOP::xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI) { if (duInfoSeiMessages.empty() || (pictureTimingSEI == NULL)) { return; } Int i=0; for (SEIMessages::iterator du = duInfoSeiMessages.begin(); du!= duInfoSeiMessages.end(); du++) { SEIDecodingUnitInfo *duInfoSEI = (SEIDecodingUnitInfo*) (*du); duInfoSEI->m_decodingUnitIdx = i; duInfoSEI->m_duSptCpbRemovalDelay = pictureTimingSEI->m_duCpbRemovalDelayMinus1[i] + 1; duInfoSEI->m_dpbOutputDuDelayPresentFlag = false; i++; } } static Void cabac_zero_word_padding(TComSlice *const pcSlice, TComPic *const pcPic, const std::size_t binCountsInNalUnits, const std::size_t numBytesInVclNalUnits, std::ostringstream &nalUnitData, const Bool cabacZeroWordPaddingEnabled) { const TComSPS &sps=*(pcSlice->getSPS()); const Int log2subWidthCxsubHeightC = (pcPic->getComponentScaleX(COMPONENT_Cb)+pcPic->getComponentScaleY(COMPONENT_Cb)); const Int minCuWidth = pcPic->getMinCUWidth(); const Int minCuHeight = pcPic->getMinCUHeight(); const Int paddedWidth = ((sps.getPicWidthInLumaSamples() + minCuWidth - 1) / minCuWidth) * minCuWidth; const Int paddedHeight= ((sps.getPicHeightInLumaSamples() + minCuHeight - 1) / minCuHeight) * minCuHeight; const Int rawBits = paddedWidth * paddedHeight * (sps.getBitDepth(CHANNEL_TYPE_LUMA) + ((2*sps.getBitDepth(CHANNEL_TYPE_CHROMA))>>log2subWidthCxsubHeightC)); const std::size_t threshold = (32/3)*numBytesInVclNalUnits + (rawBits/32); if (binCountsInNalUnits >= threshold) { // need to add additional cabac zero words (each one accounts for 3 bytes (=00 00 03)) to increase numBytesInVclNalUnits const std::size_t targetNumBytesInVclNalUnits = ((binCountsInNalUnits - (rawBits/32))*3+31)/32; if (targetNumBytesInVclNalUnits>numBytesInVclNalUnits) // It should be! { const std::size_t numberOfAdditionalBytesNeeded=targetNumBytesInVclNalUnits - numBytesInVclNalUnits; const std::size_t numberOfAdditionalCabacZeroWords=(numberOfAdditionalBytesNeeded+2)/3; const std::size_t numberOfAdditionalCabacZeroBytes=numberOfAdditionalCabacZeroWords*3; if (cabacZeroWordPaddingEnabled) { std::vector zeroBytesPadding(numberOfAdditionalCabacZeroBytes, UChar(0)); for(std::size_t i=0; i(&(zeroBytesPadding[0])), numberOfAdditionalCabacZeroBytes); printf("Adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3)); } else { printf("Standard would normally require adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3)); } } } } class EfficientFieldIRAPMapping { private: Int IRAPGOPid; Bool IRAPtoReorder; Bool swapIRAPForward; public: EfficientFieldIRAPMapping() : IRAPGOPid(-1), IRAPtoReorder(false), swapIRAPForward(false) { } Void initialize(const Bool isField, const Int gopSize, const Int POCLast, const Int numPicRcvd, const Int lastIDR, TEncGOP *pEncGop, TEncCfg *pCfg); Int adjustGOPid(const Int gopID); Int restoreGOPid(const Int gopID); Int GetIRAPGOPid() const { return IRAPGOPid; } }; Void EfficientFieldIRAPMapping::initialize(const Bool isField, const Int gopSize, const Int POCLast, const Int numPicRcvd, const Int lastIDR, TEncGOP *pEncGop, TEncCfg *pCfg ) { if(isField) { Int pocCurr; for ( Int iGOPid=0; iGOPid < gopSize; iGOPid++ ) { // determine actual POC if(POCLast == 0) //case first frame or first top field { pocCurr=0; } else if(POCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value { pocCurr = 1; } else { pocCurr = POCLast - numPicRcvd + pCfg->getGOPEntry(iGOPid).m_POC - isField; } // check if POC corresponds to IRAP NalUnitType tmpUnitType = pEncGop->getNalUnitType(pocCurr, lastIDR, isField); if(tmpUnitType >= NAL_UNIT_CODED_SLICE_BLA_W_LP && tmpUnitType <= NAL_UNIT_CODED_SLICE_CRA) // if picture is an IRAP { if(pocCurr%2 == 0 && iGOPid < gopSize-1 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid+1).m_POC-1) { // if top field and following picture in enc order is associated bottom field IRAPGOPid = iGOPid; IRAPtoReorder = true; swapIRAPForward = true; break; } if(pocCurr%2 != 0 && iGOPid > 0 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid-1).m_POC+1) { // if picture is an IRAP remember to process it first IRAPGOPid = iGOPid; IRAPtoReorder = true; swapIRAPForward = false; break; } } } } } Int EfficientFieldIRAPMapping::adjustGOPid(const Int GOPid) { if(IRAPtoReorder) { if(swapIRAPForward) { if(GOPid == IRAPGOPid) { return IRAPGOPid +1; } else if(GOPid == IRAPGOPid +1) { return IRAPGOPid; } } else { if(GOPid == IRAPGOPid -1) { return IRAPGOPid; } else if(GOPid == IRAPGOPid) { return IRAPGOPid -1; } } } return GOPid; } Int EfficientFieldIRAPMapping::restoreGOPid(const Int GOPid) { if(IRAPtoReorder) { if(swapIRAPForward) { if(GOPid == IRAPGOPid) { IRAPtoReorder = false; return IRAPGOPid +1; } else if(GOPid == IRAPGOPid +1) { return GOPid -1; } } else { if(GOPid == IRAPGOPid) { return IRAPGOPid -1; } else if(GOPid == IRAPGOPid -1) { IRAPtoReorder = false; return IRAPGOPid; } } } return GOPid; } static UInt calculateCollocatedFromL0Flag(const TComSlice *pSlice) { const Int refIdx = 0; // Zero always assumed const TComPic *refPicL0 = pSlice->getRefPic(REF_PIC_LIST_0, refIdx); const TComPic *refPicL1 = pSlice->getRefPic(REF_PIC_LIST_1, refIdx); return refPicL0->getSlice(0)->getSliceQp() > refPicL1->getSlice(0)->getSliceQp(); } static Void printHash(const HashType hashType, const std::string &digestStr) { const TChar *decodedPictureHashModeName; switch (hashType) { case HASHTYPE_MD5: decodedPictureHashModeName = "MD5"; break; case HASHTYPE_CRC: decodedPictureHashModeName = "CRC"; break; case HASHTYPE_CHECKSUM: decodedPictureHashModeName = "Checksum"; break; default: decodedPictureHashModeName = NULL; break; } if (decodedPictureHashModeName != NULL) { if (digestStr.empty()) { printf(" [%s:%s]", decodedPictureHashModeName, "?"); } else { printf(" [%s:%s]", decodedPictureHashModeName, digestStr.c_str()); } } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList& rcListPic, TComList& rcListPicYuvRecOut, std::list& accessUnitsInGOP, Bool isField, Bool isTff, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl ) { // TODO: Split this function up. TComPic* pcPic = NULL; TComPicYuv* pcPicYuvRecOut; TComSlice* pcSlice; TComOutputBitstream *pcBitstreamRedirect; pcBitstreamRedirect = new TComOutputBitstream; AccessUnit::iterator itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted xInitGOP( iPOCLast, iNumPicRcvd, isField ); m_iNumPicCoded = 0; SEIMessages leadingSeiMessages; SEIMessages nestedSeiMessages; SEIMessages duInfoSeiMessages; SEIMessages trailingSeiMessages; std::deque duData; SEIDecodingUnitInfo decodingUnitInfoSEI; EfficientFieldIRAPMapping effFieldIRAPMap; if (m_pcCfg->getEfficientFieldIRAPEnabled()) { effFieldIRAPMap.initialize(isField, m_iGopSize, iPOCLast, iNumPicRcvd, m_iLastIDR, this, m_pcCfg); } // reset flag indicating whether pictures have been encoded for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ ) { m_pcCfg->setEncodedFlag(iGOPid, false); } for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ ) { if (m_pcCfg->getEfficientFieldIRAPEnabled()) { iGOPid=effFieldIRAPMap.adjustGOPid(iGOPid); } //-- For time output for each slice clock_t iBeforeTime = clock(); /////////////////////////////////////////////////////////////////////////////////////////////////// Initial to start encoding Int iTimeOffset; Int pocCurr; if(iPOCLast == 0) //case first frame or first top field { pocCurr=0; iTimeOffset = 1; } else if(iPOCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value { pocCurr = 1; iTimeOffset = 1; } else { pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0); iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC; } if(pocCurr>=m_pcCfg->getFramesToBeEncoded()) { if (m_pcCfg->getEfficientFieldIRAPEnabled()) { iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid); } continue; } if( getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP ) { m_iLastIDR = pocCurr; } // start a new access unit: create an entry in the list of output access units accessUnitsInGOP.push_back(AccessUnit()); AccessUnit& accessUnit = accessUnitsInGOP.back(); xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField ); #if REDUCED_ENCODER_MEMORY #if SHUTTER_INTERVAL_SEI_PROCESSING pcPic->prepareForReconstruction( m_pcCfg->getShutterFilterFlag() ); #else pcPic->prepareForReconstruction(); #endif #endif // Slice data initialization pcPic->clearSliceBuffer(); pcPic->allocateNewSlice(); m_pcSliceEncoder->setSliceIdx(0); pcPic->setCurrSliceIdx(0); m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField ); pcSlice->setLastIDR(m_iLastIDR); pcSlice->setSliceIdx(0); //set default slice level flag to the same as SPS level flag pcSlice->setLFCrossSliceBoundaryFlag( pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag() ); if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P') { pcSlice->setSliceType(P_SLICE); } if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I') { pcSlice->setSliceType(I_SLICE); } // Set the nal unit type pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField)); if(pcSlice->getTemporalLayerNonReferenceFlag()) { if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_R && !(m_iGopSize == 1 && pcSlice->getSliceType() == I_SLICE)) // Add this condition to avoid POC issues with encoder_intra_main.cfg configuration (see #1127 in bug tracker) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N); } if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N); } if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N); } } if (m_pcCfg->getEfficientFieldIRAPEnabled()) { if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // IRAP picture { m_associatedIRAPType = pcSlice->getNalUnitType(); m_associatedIRAPPOC = pocCurr; } pcSlice->setAssociatedIRAPType(m_associatedIRAPType); pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC); } // Do decoding refresh marking if any pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled()); m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid); if (!m_pcCfg->getEfficientFieldIRAPEnabled()) { if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // IRAP picture { m_associatedIRAPType = pcSlice->getNalUnitType(); m_associatedIRAPPOC = pocCurr; } pcSlice->setAssociatedIRAPType(m_associatedIRAPType); pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC); } if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP()) || (m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pcSlice->getAssociatedIRAPType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getAssociatedIRAPType() <= NAL_UNIT_CODED_SLICE_CRA && pcSlice->getAssociatedIRAPPOC() == pcSlice->getPOC()+1) ) { pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3, m_pcCfg->getEfficientFieldIRAPEnabled()); } pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS()); if(pcSlice->getTLayer() > 0 && !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N // Check if not a leading picture || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R ) ) { if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag()) { if(pcSlice->getTemporalLayerNonReferenceFlag()) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R); } } else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic)) { Bool isSTSA=true; for(Int ii=iGOPid+1;(iigetGOPSize() && isSTSA==true);ii++) { Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId; if(lTid==pcSlice->getTLayer()) { const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii); for(Int jj=0;jjgetNumberOfPictures();jj++) { if(nRPS->getUsed(jj)) { Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj); Int kk=0; for(kk=0;kkgetGOPSize();kk++) { if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc) { break; } } Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId; if(tTid >= pcSlice->getTLayer()) { isSTSA=false; break; } } } } } if(isSTSA==true) { if(pcSlice->getTemporalLayerNonReferenceFlag()) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R); } } } } arrangeLongtermPicturesInRPS(pcSlice, rcListPic); TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification(); refPicListModification->setRefPicListModificationFlagL0(0); refPicListModification->setRefPicListModificationFlagL1(0); pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures())); pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures())); // Set reference list pcSlice->setRefPicList ( rcListPic ); // Slice info. refinement if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) ) { pcSlice->setSliceType ( P_SLICE ); } if (pcSlice->getPOC() > m_RASPOCforResetEncoder && m_pcCfg->getResetEncoderStateAfterIRAP()) { // need to reset encoder decisions. m_pcSliceEncoder->resetEncoderDecisions(); if (pcSlice->getSPS()->getUseSAO()) { m_pcSAO->resetEncoderDecisions(); } m_RASPOCforResetEncoder=MAX_INT; } if (pcSlice->isIRAP()) { m_RASPOCforResetEncoder = pcSlice->getPOC(); } pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); #if MCTS_EXTRACTION SliceType encCABACTableIdx = pcSlice->getEncCABACTableIdx(); Bool encCabacInitFlag = (pcSlice->getSliceType() != encCABACTableIdx && encCABACTableIdx != I_SLICE) ? true : false; pcSlice->setCabacInitFlag(encCabacInitFlag); #endif if (pcSlice->getSliceType() == B_SLICE) { const UInt uiColFromL0 = calculateCollocatedFromL0Flag(pcSlice); pcSlice->setColFromL0Flag(uiColFromL0); Bool bLowDelay = true; Int iCurrPOC = pcSlice->getPOC(); Int iRefIdx = 0; for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } pcSlice->setCheckLDC(bLowDelay); } else { pcSlice->setCheckLDC(true); } //------------------------------------------------------------- pcSlice->setRefPOCList(); pcSlice->setList1IdxToList0Idx(); if (m_pcEncTop->getTMVPModeId() == 2) { if (iGOPid == 0) // first picture in SOP (i.e. forward B) { pcSlice->setEnableTMVPFlag(0); } else { // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0. pcSlice->setEnableTMVPFlag(1); } } else if (m_pcEncTop->getTMVPModeId() == 1) { pcSlice->setEnableTMVPFlag(1); } else { pcSlice->setEnableTMVPFlag(0); } // set adaptive search range for non-intra-slices if (m_pcCfg->getUseASR() && pcSlice->getSliceType()!=I_SLICE) { m_pcSliceEncoder->setSearchRange(pcSlice); } Bool bGPBcheck=false; if ( pcSlice->getSliceType() == B_SLICE) { if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { bGPBcheck=true; Int i; for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ ) { if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ) { bGPBcheck=false; break; } } } } if(bGPBcheck) { pcSlice->setMvdL1ZeroFlag(true); } else { pcSlice->setMvdL1ZeroFlag(false); } Double lambda = 0.0; Int actualHeadBits = 0; Int actualTotalBits = 0; Int estimatedBits = 0; Int tmpBitsBeforeWriting = 0; if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments? { Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid ); if ( pcPic->getSlice(0)->getSliceType() == I_SLICE ) { frameLevel = 0; } m_pcRateCtrl->initRCPic( frameLevel ); estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); if (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0) { Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate(); // prevent overflow if (estimatedCpbFullness - estimatedBits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f)) { estimatedBits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f); } estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate(); // prevent underflow if (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound()) { estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound()); } m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits); } Int sliceQP = m_pcCfg->getInitialQP(); if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified { Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 ); Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames ); Double dQPFactor = 0.57*dLambda_scale; Int SHIFT_QP = 12; Int bitdepth_luma_qp_scale = 0; Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP; lambda = dQPFactor*pow( 2.0, qp_temp/3.0 ); } else if ( frameLevel == 0 ) // intra case, but use the model { m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others? if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case { Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits(); bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits ); if (m_pcRateCtrl->getCpbSaturationEnabled() ) { Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate(); // prevent overflow if (estimatedCpbFullness - bits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f)) { bits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f); } estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate(); // prevent underflow if (estimatedCpbFullness - bits < m_pcRateCtrl->getRCPic()->getLowerBound()) { bits = estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound(); } } if ( bits < 200 ) { bits = 200; } m_pcRateCtrl->getRCPic()->setTargetBits( bits ); } list listPreviousPicture = m_pcRateCtrl->getPicList(); m_pcRateCtrl->getRCPic()->getLCUInitTargetBits(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } else // normal case { list listPreviousPicture = m_pcRateCtrl->getPicList(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP ); m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP ); m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); } UInt uiNumSliceSegments = 1; // Allocate some coders, now the number of tiles are known. const Int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1); const Int numSubstreamRows = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->getFrameHeightInCtus() : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1); const Int numSubstreams = numSubstreamRows * numSubstreamsColumns; std::vector substreamsOut(numSubstreams); // now compress (trial encode) the various slice segments (slices, and dependent slices) { const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame(); pcSlice->setSliceCurStartCtuTsAddr( 0 ); pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 ); for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; ) { m_pcSliceEncoder->precompressSlice( pcPic ); m_pcSliceEncoder->compressSlice ( pcPic, false, false ); const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr(); if (curSliceSegmentEnd < numberOfCtusInFrame) { const Bool bNextSegmentIsDependentSlice=curSliceSegmentEndgetSliceCurEndCtuTsAddr(); const UInt sliceBits=pcSlice->getSliceBits(); pcPic->allocateNewSlice(); // prepare for next slice pcPic->setCurrSliceIdx ( uiNumSliceSegments ); m_pcSliceEncoder->setSliceIdx ( uiNumSliceSegments ); pcSlice = pcPic->getSlice ( uiNumSliceSegments ); assert(pcSlice->getPPS()!=0); pcSlice->copySliceInfo ( pcPic->getSlice(uiNumSliceSegments-1) ); pcSlice->setSliceIdx ( uiNumSliceSegments ); if (bNextSegmentIsDependentSlice) { pcSlice->setSliceBits(sliceBits); } else { pcSlice->setSliceCurStartCtuTsAddr ( curSliceSegmentEnd ); pcSlice->setSliceBits(0); } pcSlice->setDependentSliceSegmentFlag(bNextSegmentIsDependentSlice); pcSlice->setSliceSegmentCurStartCtuTsAddr ( curSliceSegmentEnd ); // TODO: optimise cabac_init during compress slice to improve multi-slice operation // pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); uiNumSliceSegments ++; } nextCtuTsAddr = curSliceSegmentEnd; } } duData.clear(); pcSlice = pcPic->getSlice(0); // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() ) { m_pcSAO->getPreDBFStatistics(pcPic); } //-- Loop filter Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); m_pcLoopFilter->setCfg(bLFCrossTileBoundary); if ( m_pcCfg->getDeblockingFilterMetric() ) { if ( m_pcCfg->getDeblockingFilterMetric()==2 ) { applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid); } else { applyDeblockingFilterMetric(pcPic, uiNumSliceSegments); } } m_pcLoopFilter->loopFilterPic( pcPic ); #if JVET_X0048_X0103_FILM_GRAIN if (m_pcCfg->getFilmGrainAnalysisEnabled()) { int filteredFrame = m_pcCfg->getIntraPeriod() < 1 ? 2 * m_pcCfg->getFrameRate() : m_pcCfg->getIntraPeriod(); bool ready_to_analyze = pcPic->getPOC() % filteredFrame ? false : true; // either it is mctf denoising or external source for film grain analysis. note: if mctf is used, it is different from mctf for encoding. if (ready_to_analyze) { m_FGAnalyser.initBufs(pcPic); m_FGAnalyser.estimate_grain(pcPic); } } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// File writing // Set entropy coder m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder ); // write various parameter sets //bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcPic->getSlice(0)->getSliceType() == I_SLICE)); bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcSlice->isIRAP())); if (writePS) { m_pcEncTop->setParamSetChanged(pcSlice->getSPS()->getSPSId(), pcSlice->getPPS()->getPPSId()); } actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS); if (writePS) { // create prefix SEI messages at the beginning of the sequence assert(leadingSeiMessages.empty()); #if MCTS_EXTRACTION xCreateIRAPLeadingSEIMessages(leadingSeiMessages, m_pcEncTop->getVPS(), pcSlice->getSPS(), pcSlice->getPPS()); #else xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS()); #endif m_bSeqFirst = false; } if (m_pcCfg->getAccessUnitDelimiter()) { xWriteAccessUnitDelimiter(accessUnit, pcSlice); } // reset presence of BP SEI indication m_bufferingPeriodSEIPresentInAU = false; // create prefix SEI associated with a picture xCreatePerPictureSEIMessages(iGOPid, leadingSeiMessages, nestedSeiMessages, pcSlice); /* use the main bitstream buffer for storing the marshalled picture */ m_pcEntropyCoder->setBitstream(NULL); pcSlice = pcPic->getSlice(0); if (pcSlice->getSPS()->getUseSAO()) { Bool sliceEnabled[MAX_NUM_COMPONENT]; TComBitCounter tempBitCounter; tempBitCounter.resetBits(); m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter); m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice); m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(), m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma(), m_pcCfg->getSaoCtuBoundary()); m_pcSAO->PCMLFDisableProcess(pcPic); m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL); //assign SAO slice header for(Int s=0; s< uiNumSliceSegments; s++) { pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]); assert(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]); pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]); } } // pcSlice is currently slice 0. std::size_t binCountsInNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10) std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10) for( UInt sliceSegmentStartCtuTsAddr = 0, sliceIdxCount=0; sliceSegmentStartCtuTsAddr < pcPic->getPicSym()->getNumberOfCtusInFrame(); sliceIdxCount++, sliceSegmentStartCtuTsAddr=pcSlice->getSliceSegmentCurEndCtuTsAddr() ) { pcSlice = pcPic->getSlice(sliceIdxCount); if(sliceIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE) { pcSlice->checkColRefIdx(sliceIdxCount, pcPic); } pcPic->setCurrSliceIdx(sliceIdxCount); m_pcSliceEncoder->setSliceIdx(sliceIdxCount); pcSlice->setRPS(pcPic->getSlice(0)->getRPS()); pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx()); for ( UInt ui = 0 ; ui < numSubstreams; ui++ ) { substreamsOut[ui].clear(); } m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder ); m_pcEntropyCoder->resetEntropy ( pcSlice ); /* start slice NALunit */ OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer() ); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); pcSlice->setNoRaslOutputFlag(false); if (pcSlice->isIRAP()) { if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP) { pcSlice->setNoRaslOutputFlag(true); } //the inference for NoOutputPriorPicsFlag // KJS: This cannot happen at the encoder if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag()) { if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) { pcSlice->setNoOutputPriorPicsFlag(true); } } } pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); #if MCTS_EXTRACTION encCABACTableIdx = pcSlice->getEncCABACTableIdx(); encCabacInitFlag = (pcSlice->getSliceType() != encCABACTableIdx && encCABACTableIdx != I_SLICE) ? true : false; pcSlice->setCabacInitFlag(encCabacInitFlag); #endif tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits(); m_pcEntropyCoder->encodeSliceHeader(pcSlice); actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting ); pcSlice->setFinalized(true); pcSlice->clearSubstreamSizes( ); { UInt numBinsCoded = 0; m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded); binCountsInNalUnits+=numBinsCoded; } { // Construct the final bitstream by concatenating substreams. // The final bitstream is either nalu.m_Bitstream or pcBitstreamRedirect; // Complete the slice header info. m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder ); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice ); // Append substreams... TComOutputBitstream *pcOut = pcBitstreamRedirect; const Int numZeroSubstreamsAtStartOfSlice = pcPic->getSubstreamForCtuAddr(pcSlice->getSliceSegmentCurStartCtuTsAddr(), false, pcSlice); const Int numSubstreamsToCode = pcSlice->getNumberOfSubstreamSizes()+1; for ( UInt ui = 0 ; ui < numSubstreamsToCode; ui++ ) { pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice])); } } // If current NALU is the first NALU of slice (containing slice header) and more NALUs exist (due to multiple dependent slices) then buffer it. // If current NALU is the last NALU of slice and a NALU was buffered, then (a) Write current NALU (b) Update an write buffered NALU at approproate location in NALU list. Bool bNALUAlignedWrittenToList = false; // used to ensure current NALU is not written more than once to the NALU list. xAttachSliceDataToNalUnit(nalu, pcBitstreamRedirect); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; numBytesInVclNalUnits += (std::size_t)(accessUnit.back()->m_nalUnitData.str().size()); bNALUAlignedWrittenToList = true; if (!bNALUAlignedWrittenToList) { nalu.m_Bitstream.writeAlignZero(); accessUnit.push_back(new NALUnitEBSP(nalu)); } if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) && ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) ) { UInt numNalus = 0; UInt numRBSPBytes = 0; for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++) { numRBSPBytes += UInt((*it)->m_nalUnitData.str().size()); numNalus ++; } duData.push_back(DUData()); duData.back().accumBitsDU = ( numRBSPBytes << 3 ); duData.back().accumNalsDU = numNalus; } } // end iteration over slices // cabac_zero_words processing cabac_zero_word_padding(pcSlice, pcPic, binCountsInNalUnits, numBytesInVclNalUnits, accessUnit.back()->m_nalUnitData, m_pcCfg->getCabacZeroWordPaddingEnabled()); pcPic->compressMotion(); //-- For time output for each slice Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; std::string digestStr; if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE) { SEIDecodedPictureHash *decodedPictureHashSei = new SEIDecodedPictureHash(); m_seiEncoder.initDecodedPictureHashSEI(decodedPictureHashSei, pcPic, digestStr, pcSlice->getSPS()->getBitDepths()); trailingSeiMessages.push_back(decodedPictureHashSei); } m_pcCfg->setEncodedFlag(iGOPid, true); Double PSNR_Y; xCalculateAddPSNRs( isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, dEncTime, ip_conversion, snr_conversion, outputLogCtrl, &PSNR_Y ); // Only produce the Green Metadata SEI message with the last picture. if( m_pcCfg->getSEIGreenMetadataInfoSEIEnable() && pcSlice->getPOC() == ( m_pcCfg->getFramesToBeEncoded() - 1 ) ) { SEIGreenMetadataInfo *seiGreenMetadataInfo = new SEIGreenMetadataInfo; m_seiEncoder.initSEIGreenMetadataInfo(seiGreenMetadataInfo, (UInt)(PSNR_Y * 100 + 0.5)); trailingSeiMessages.push_back(seiGreenMetadataInfo); } xWriteTrailingSEIMessages(trailingSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS()); printHash(m_pcCfg->getDecodedPictureHashSEIType(), digestStr); if ( m_pcCfg->getUseRateCtrl() ) { Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP(); Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda(); if ( avgLambda < 0.0 ) { avgLambda = lambda; } m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType()); m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() ); m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits ); if ( pcSlice->getSliceType() != I_SLICE ) { m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits ); } else // for intra picture, the estimated bits are used to update the current status in the GOP { m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits ); } if (m_pcRateCtrl->getCpbSaturationEnabled()) { m_pcRateCtrl->updateCpbState(actualTotalBits); printf(" [CPB %6d bits]", m_pcRateCtrl->getCpbState()); } } xCreatePictureTimingSEI(m_pcCfg->getEfficientFieldIRAPEnabled()?effFieldIRAPMap.GetIRAPGOPid():0, leadingSeiMessages, nestedSeiMessages, duInfoSeiMessages, pcSlice, isField, duData); if (m_pcCfg->getScalableNestingSEIEnabled()) { xCreateScalableNestingSEI (leadingSeiMessages, nestedSeiMessages); } xWriteLeadingSEIMessages(leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData); xWriteDuSEIMessages(duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData); pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut); pcPic->setReconMark ( true ); m_bFirst = false; m_iNumPicCoded++; m_totalCoded ++; /* logging: insert a newline at end of picture period */ printf("\n"); fflush(stdout); if (m_pcCfg->getEfficientFieldIRAPEnabled()) { iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid); } #if REDUCED_ENCODER_MEMORY pcPic->releaseReconstructionIntermediateData(); if (!isField) // don't release the source data for field-coding because the fields are dealt with in pairs. // TODO: release source data for interlace simulations. { pcPic->releaseEncoderSourceImageData(); } #endif } // iGOPid-loop delete pcBitstreamRedirect; assert ( (m_iNumPicCoded == iNumPicRcvd) ); } Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const TEncAnalyze::OutputLogControl &outputLogCtrl, const BitDepths &bitDepths) { assert (uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic()); //--CFG_KDY const Int rateMultiplier=(isField?2:1); m_gcAnalyzeAll.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio()); m_gcAnalyzeI.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio()); m_gcAnalyzeP.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio()); m_gcAnalyzeB.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio()); const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc(); //-- all printf( "\n\nSUMMARY --------------------------------------------------------\n" ); m_gcAnalyzeAll.printOut('a', chFmt, outputLogCtrl, bitDepths); printf( "\n\nI Slices--------------------------------------------------------\n" ); m_gcAnalyzeI.printOut('i', chFmt, outputLogCtrl, bitDepths); printf( "\n\nP Slices--------------------------------------------------------\n" ); m_gcAnalyzeP.printOut('p', chFmt, outputLogCtrl, bitDepths); printf( "\n\nB Slices--------------------------------------------------------\n" ); m_gcAnalyzeB.printOut('b', chFmt, outputLogCtrl, bitDepths); if (!m_pcCfg->getSummaryOutFilename().empty()) { m_gcAnalyzeAll.printSummary(chFmt, outputLogCtrl, bitDepths, m_pcCfg->getSummaryOutFilename()); } if (!m_pcCfg->getSummaryPicFilenameBase().empty()) { m_gcAnalyzeI.printSummary(chFmt, outputLogCtrl, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"I.txt"); m_gcAnalyzeP.printSummary(chFmt, outputLogCtrl, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"P.txt"); m_gcAnalyzeB.printSummary(chFmt, outputLogCtrl, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"B.txt"); } if(isField) { //-- interlaced summary m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate() / (Double)m_pcCfg->getTemporalSubsampleRatio()); m_gcAnalyzeAll_in.setBits(m_gcAnalyzeAll.getBits()); // prior to the above statement, the interlace analyser does not contain the correct total number of bits. printf( "\n\nSUMMARY INTERLACED ---------------------------------------------\n" ); m_gcAnalyzeAll_in.printOut('a', chFmt, outputLogCtrl, bitDepths); if (!m_pcCfg->getSummaryOutFilename().empty()) { m_gcAnalyzeAll_in.printSummary(chFmt, outputLogCtrl, bitDepths, m_pcCfg->getSummaryOutFilename()); } } printf("\nRVM: %.3lf\n" , xCalculateRVM()); } Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, UInt64& ruiDist ) { Bool bCalcDist = false; m_pcLoopFilter->setCfg(m_pcCfg->getLFCrossTileBoundaryFlag()); m_pcLoopFilter->loopFilterPic( pcPic ); if (!bCalcDist) { ruiDist = xFindDistortionFrame(pcPic->getPicYuvOrg(), pcPic->getPicYuvRec(), pcPic->getPicSym()->getSPS().getBitDepths()); } } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Void TEncGOP::xInitGOP( Int iPOCLast, Int iNumPicRcvd, Bool isField ) { assert( iNumPicRcvd > 0 ); // Exception for the first frames if ( ( isField && (iPOCLast == 0 || iPOCLast == 1) ) || (!isField && (iPOCLast == 0)) ) { m_iGopSize = 1; } else { m_iGopSize = m_pcCfg->getGOPSize(); } assert (m_iGopSize > 0); return; } Void TEncGOP::xGetBuffer( TComList& rcListPic, TComList& rcListPicYuvRecOut, Int iNumPicRcvd, Int iTimeOffset, TComPic*& rpcPic, TComPicYuv*& rpcPicYuvRecOut, Int pocCurr, Bool isField) { Int i; // Rec. output TComList::iterator iterPicYuvRec = rcListPicYuvRecOut.end(); if (isField && pocCurr > 1 && m_iGopSize!=1) { iTimeOffset--; } for ( i = 0; i < (iNumPicRcvd - iTimeOffset + 1); i++ ) { iterPicYuvRec--; } rpcPicYuvRecOut = *(iterPicYuvRec); // Current pic. TComList::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); rpcPic->setCurrSliceIdx(0); if (rpcPic->getPOC() == pocCurr) { break; } iterPic++; } assert (rpcPic != NULL); assert (rpcPic->getPOC() == pocCurr); return; } UInt64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths) { UInt64 uiTotalDiff = 0; for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); Pel* pSrc0 = pcPic0 ->getAddr(ch); Pel* pSrc1 = pcPic1 ->getAddr(ch); UInt uiShift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepths.recon[toChannelType(ch)]-8); const Int iStride = pcPic0->getStride(ch); const Int iWidth = pcPic0->getWidth(ch); const Int iHeight = pcPic0->getHeight(ch); for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iTemp = pSrc0[x] - pSrc1[x]; uiTotalDiff += UInt64((iTemp*iTemp) >> uiShift); } pSrc0 += iStride; pSrc1 += iStride; } } return uiTotalDiff; } Void TEncGOP::xCalculateAddPSNRs( const Bool isField, const Bool isFieldTopFieldFirst, const Int iGOPid, TComPic* pcPic, const AccessUnit&accessUnit, TComList &rcListPic, const Double dEncTime, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl, Double* PSNR_Y ) { xCalculateAddPSNR( pcPic, pcPic->getPicYuvRec(), accessUnit, dEncTime, ip_conversion, snr_conversion, outputLogCtrl, PSNR_Y ); //In case of field coding, compute the interlaced PSNR for both fields if(isField) { Bool bothFieldsAreEncoded = false; Int correspondingFieldPOC = pcPic->getPOC(); Int currentPicGOPPoc = m_pcCfg->getGOPEntry(iGOPid).m_POC; if(pcPic->getPOC() == 0) { // particular case for POC 0 and 1. // If they are not encoded first and separately from other pictures, we need to change this // POC 0 is always encoded first then POC 1 is encoded bothFieldsAreEncoded = false; } else if(pcPic->getPOC() == 1) { // if we are at POC 1, POC 0 has been encoded for sure correspondingFieldPOC = 0; bothFieldsAreEncoded = true; } else { if(pcPic->getPOC()%2 == 1) { correspondingFieldPOC -= 1; // all odd POC are associated with the preceding even POC (e.g poc 1 is associated to poc 0) currentPicGOPPoc -= 1; } else { correspondingFieldPOC += 1; // all even POC are associated with the following odd POC (e.g poc 0 is associated to poc 1) currentPicGOPPoc += 1; } for(Int i = 0; i < m_iGopSize; i ++) { if(m_pcCfg->getGOPEntry(i).m_POC == currentPicGOPPoc) { bothFieldsAreEncoded = m_pcCfg->getGOPEntry(i).m_isEncoded; break; } } } if(bothFieldsAreEncoded) { //get complementary top field TComList::iterator iterPic = rcListPic.begin(); while ((*iterPic)->getPOC() != correspondingFieldPOC) { iterPic ++; } TComPic* correspondingFieldPic = *(iterPic); if( (pcPic->isTopField() && isFieldTopFieldFirst) || (!pcPic->isTopField() && !isFieldTopFieldFirst)) { xCalculateInterlacedAddPSNR(pcPic, correspondingFieldPic, pcPic->getPicYuvRec(), correspondingFieldPic->getPicYuvRec(), snr_conversion, outputLogCtrl, PSNR_Y ); } else { xCalculateInterlacedAddPSNR(correspondingFieldPic, pcPic, correspondingFieldPic->getPicYuvRec(), pcPic->getPicYuvRec(), snr_conversion, outputLogCtrl, PSNR_Y ); } } } } Void TEncGOP::xCalculateAddPSNR( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit& accessUnit, Double dEncTime, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl, Double* PSNR_Y ) { TEncAnalyze::ResultData result; // calculate colour space of reconstructed data TComPicYuv cscd; if (snr_conversion!=IPCOLOURSPACE_UNCHANGED) { cscd.createWithoutCUInfo(pcPicD->getWidth(COMPONENT_Y), pcPicD->getHeight(COMPONENT_Y), pcPicD->getChromaFormat() ); TVideoIOYuv::ColourSpaceConvert(*pcPicD, cscd, snr_conversion, false); } TComPicYuv &picd=(snr_conversion==IPCOLOURSPACE_UNCHANGED)?*pcPicD : cscd; // calculate colour space of source data TComPicYuv tmpTrueOrgInInternalMap; const TComPicYuv *pOrgPicYuv=0; const bool bOrgDataHasBeenAdjusted=m_pcCfg->getGopBasedTemporalFilterEnabled(); if (snr_conversion==IPCOLOURSPACE_UNCHANGED) { // Comparison in same colour space as internal. if (bOrgDataHasBeenAdjusted) { // have to map true original data into internal data format tmpTrueOrgInInternalMap.createWithoutCUInfo(pcPicD->getWidth(COMPONENT_Y), pcPicD->getHeight(COMPONENT_Y), pcPicD->getChromaFormat()); TVideoIOYuv::ColourSpaceConvert(*pcPic->getPicYuvTrueOrg(), tmpTrueOrgInInternalMap, ip_conversion, true); pOrgPicYuv = &tmpTrueOrgInInternalMap; } else { // original data not corrupted, so just use original pOrgPicYuv = pcPic->getPicYuvOrg(); } } else { // we are doing comparison in true original, which has not been corrupted. pOrgPicYuv = pcPic ->getPicYuvTrueOrg(); } //===== calculate PSNR ===== if (outputLogCtrl.printXPSNR && pcPicD->getChromaFormat() != CHROMA_400) { const Pel* pOrg[MAX_NUM_COMPONENT]; Double dWeightPel[MAX_NUM_COMPONENT]; Int iWeightSize[MAX_NUM_COMPONENT] = {1, 1, 1}; const Pel* pRec[MAX_NUM_COMPONENT]; Int iOrgStride[MAX_NUM_COMPONENT], iRecStride[MAX_NUM_COMPONENT]; Int iWidth[MAX_NUM_COMPONENT], iHeight[MAX_NUM_COMPONENT], iSize[MAX_NUM_COMPONENT]; UInt64 uiSSDtemp[MAX_NUM_COMPONENT]; UInt uiShiftWidth[MAX_NUM_COMPONENT], uiShiftHeight[MAX_NUM_COMPONENT]; Intermediate_Int iDiff; for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); iOrgStride[ch] = pOrgPicYuv->getStride(ch); iRecStride[ch] = picd.getStride(ch); iWidth[ch] = pcPicD->getWidth (ch) - (m_pcEncTop->getSourcePadding(0) >> pcPic->getComponentScaleX(ch)); iHeight[ch] = pcPicD->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch)); iSize[ch] = iWidth[ch]*iHeight[ch]; uiSSDtemp[ch] = 0; uiShiftWidth[ch] = (ch == COMPONENT_Y || pcPicD->getChromaFormat() == CHROMA_444) ? 0 : 1; uiShiftHeight[ch] = (ch == COMPONENT_Y || pcPicD->getChromaFormat() == CHROMA_444 || pcPicD->getChromaFormat() == CHROMA_422) ? 0 : 1; dWeightPel[ch] = m_pcCfg->getXPSNRWeight(ch); pOrg[ch] = pOrgPicYuv->getAddr(ch); pRec[ch] = picd.getAddr(ch); } Double dSSDtemp=0; std::vector vecSSEChroma(iSize[COMPONENT_Cb], Double(0)); for(Int y = 0, t= 0; y < iHeight[COMPONENT_Cb]; y++ ) { for(Int x = 0; x < iWidth[COMPONENT_Cb]; x++, t++) { UInt64 uiSE_cb, uiSE_cr; iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Cb][x] - (Intermediate_Int)pRec[COMPONENT_Cb][x] ); uiSE_cb = iDiff * iDiff; iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Cr][x] - (Intermediate_Int)pRec[COMPONENT_Cr][x] ); uiSE_cr = iDiff * iDiff; uiSSDtemp[COMPONENT_Cb] += uiSE_cb; uiSSDtemp[COMPONENT_Cr] += uiSE_cr; vecSSEChroma[t] = dWeightPel[COMPONENT_Cb] * (Double) uiSE_cb + dWeightPel[COMPONENT_Cr] * (Double) uiSE_cr; } pOrg[COMPONENT_Cb] += iOrgStride[COMPONENT_Cb]; pRec[COMPONENT_Cb] += iRecStride[COMPONENT_Cb]; pOrg[COMPONENT_Cr] += iOrgStride[COMPONENT_Cr]; pRec[COMPONENT_Cr] += iRecStride[COMPONENT_Cr]; } for(Int y = 0; y < iHeight[COMPONENT_Y]; y++ ) { UInt y_step_chroma = (y >> uiShiftHeight[COMPONENT_Cb]) * iWidth[COMPONENT_Cb]; for(Int x = 0; x < iWidth[COMPONENT_Y]; x++) { UInt64 uiSE_y; UInt x_step_chroma = (x >> uiShiftWidth[COMPONENT_Cb]); iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Y][x] - (Intermediate_Int)pRec[COMPONENT_Y][x] ); uiSE_y = iDiff * iDiff; uiSSDtemp[COMPONENT_Y] += uiSE_y; dSSDtemp += sqrt(dWeightPel[COMPONENT_Y] * (Double) uiSE_y + vecSSEChroma[y_step_chroma+x_step_chroma]); } pOrg[COMPONENT_Y] += iOrgStride[COMPONENT_Y]; pRec[COMPONENT_Y] += iRecStride[COMPONENT_Y]; } Double fWValue = 0; for( Int chan = 0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); const UInt maxval = 255 << (pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(ch)) - 8); const Double fRefValue = (Double) maxval * maxval * iSize[ch]; result.psnr[ch] = ( uiSSDtemp[ch] ? 10.0 * log10( fRefValue / (Double)uiSSDtemp[ch] ) : 999.99 ); result.MSEyuvframe[ch] = (Double)uiSSDtemp[ch]/(iSize[ch]); fWValue += (Double) iWeightSize[ch] * (Double) iSize[ch]; } const Double maxval = 255 << (pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(COMPONENT_Y)) - 8); fWValue = Double( maxval * fWValue); result.xpsnr = dSSDtemp ? 20.0 * log10( fWValue / dSSDtemp) : 999.99; } else { for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); const Pel* pOrg = pOrgPicYuv->getAddr(ch); const Int iOrgStride = pOrgPicYuv->getStride(ch); Pel* pRec = picd.getAddr(ch); const Int iRecStride = picd.getStride(ch); const Int iWidth = pcPicD->getWidth (ch) - (m_pcEncTop->getSourcePadding(0) >> pcPic->getComponentScaleX(ch)); const Int iHeight = pcPicD->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch)); Int iSize = iWidth*iHeight; UInt64 uiSSDtemp=0; for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] ); uiSSDtemp += iDiff * iDiff; } pOrg += iOrgStride; pRec += iRecStride; } const Int maxval = 255 << (pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(ch)) - 8); const Double fRefValue = (Double) maxval * maxval * iSize; result.psnr[ch] = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 ); result.MSEyuvframe[ch] = (Double)uiSSDtemp/(iSize); } } #if EXTENSION_360_VIDEO m_ext360.calculatePSNRs(pcPic); #endif //===== calculate MS-SSIM ===== if (outputLogCtrl.printMSSSIM) { for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch = ComponentID(chan); const Pel* pOrg = pOrgPicYuv->getAddr(ch); const Int orgStride = pOrgPicYuv->getStride(ch); const Pel* pRec = picd.getAddr(ch); const Int recStride = picd.getStride(ch); const Int width = pcPicD->getWidth (ch) - (m_pcEncTop->getSourcePadding(0) >> pcPic->getComponentScaleX(ch)); const Int height = pcPicD->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch)); const UInt bitDepth = pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(ch)); result.MSSSIM[ch] = xCalculateMSSSIM (pOrg, orgStride, pRec, recStride, width, height, bitDepth); } } /* calculate the size of the access unit, excluding: * - SEI NAL units */ UInt numRBSPBytes = 0; for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++) { UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size()); if (m_pcCfg->getSummaryVerboseness() > 0) { printf("*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal); } if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI) { numRBSPBytes += numRBSPBytes_nal; // add start code bytes (Annex B) if (it == accessUnit.begin() || (*it)->m_nalUnitType == NAL_UNIT_VPS || (*it)->m_nalUnitType == NAL_UNIT_SPS || (*it)->m_nalUnitType == NAL_UNIT_PPS) { numRBSPBytes += 4; } else { numRBSPBytes += 3; } } } UInt uibits = numRBSPBytes * 8; m_vRVM_RP.push_back( uibits ); //===== add distortion metrics ===== result.bits=(Double)uibits; m_gcAnalyzeAll.addResult (result); #if EXTENSION_360_VIDEO m_ext360.addResult(m_gcAnalyzeAll); #endif TComSlice* pcSlice = pcPic->getSlice(0); if (pcSlice->isIntra()) { m_gcAnalyzeI.addResult (result); #if EXTENSION_360_VIDEO m_ext360.addResult(m_gcAnalyzeI); #endif *PSNR_Y = result.psnr[COMPONENT_Y]; } if (pcSlice->isInterP()) { m_gcAnalyzeP.addResult (result); #if EXTENSION_360_VIDEO m_ext360.addResult(m_gcAnalyzeP); #endif *PSNR_Y = result.psnr[COMPONENT_Y]; } if (pcSlice->isInterB()) { m_gcAnalyzeB.addResult (result); #if EXTENSION_360_VIDEO m_ext360.addResult(m_gcAnalyzeB); #endif *PSNR_Y = result.psnr[COMPONENT_Y]; } TChar c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B'); if (!pcSlice->isReferenced()) { c += 32; } #if ADAPTIVE_QP_SELECTION printf("POC %4d TId: %1d ( %c-SLICE, nQP %d QP %d ) %10d bits", pcSlice->getPOC(), pcSlice->getTLayer(), c, pcSlice->getSliceQpBase(), pcSlice->getSliceQp(), uibits ); #else printf("POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits", pcSlice->getPOC()-pcSlice->getLastIDR(), pcSlice->getTLayer(), c, pcSlice->getSliceQp(), uibits ); #endif printf(" [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", result.psnr[COMPONENT_Y], result.psnr[COMPONENT_Cb], result.psnr[COMPONENT_Cr] ); if (outputLogCtrl.printHexPerPOCPSNRs) { uint64_t xPsnr[MAX_NUM_COMPONENT]; for (int i = 0; i < MAX_NUM_COMPONENT; i++) { copy(reinterpret_cast(&result.psnr[i]), reinterpret_cast(&result.psnr[i]) + sizeof(result.psnr[i]), reinterpret_cast(&xPsnr[i])); } printf(" [xY %16" PRIx64 " xU %16" PRIx64 " xv %16" PRIx64 "]", xPsnr[COMPONENT_Y], xPsnr[COMPONENT_Cb], xPsnr[COMPONENT_Cr]); } if (outputLogCtrl.printMSSSIM) { printf(" [MS-SSIM Y %1.6lf U %1.6lf V %1.6lf]", result.MSSSIM[COMPONENT_Y], result.MSSSIM[COMPONENT_Cb], result.MSSSIM[COMPONENT_Cr] ); } if (outputLogCtrl.printXPSNR) { printf(" [xPSNR %6.4lf dB]", result.xpsnr); } if (outputLogCtrl.printFrameMSE) { printf(" [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", result.MSEyuvframe[COMPONENT_Y], result.MSEyuvframe[COMPONENT_Cb], result.MSEyuvframe[COMPONENT_Cr] ); } #if EXTENSION_360_VIDEO m_ext360.printPerPOCInfo(); #endif printf(" [ET %5.0f ]", dEncTime ); // printf(" [WP %d]", pcSlice->getUseWeightedPrediction()); for (Int iRefList = 0; iRefList < 2; iRefList++) { printf(" [L%d ", iRefList); for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++) { printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)-pcSlice->getLastIDR()); } printf("]"); } cscd.destroy(); } Double TEncGOP::xCalculateMSSSIM (const Pel *pOrg, const Int orgStride, const Pel* pRec, const Int recStride, const Int width, const Int height, const UInt bitDepth) { const Int MAX_MSSSIM_SCALE = 5; const Int WEIGHTING_MID_TAP = 5; const Int WEIGHTING_SIZE = WEIGHTING_MID_TAP*2+1; UInt maxScale; // For low resolution videos determine number of scales if (width < 22 || height < 22) { maxScale = 1; } else if (width < 44 || height < 44) { maxScale = 2; } else if (width < 88 || height < 88) { maxScale = 3; } else if (width < 176 || height < 176) { maxScale = 4; } else { maxScale = 5; } assert(maxScale>0 && maxScale<=MAX_MSSSIM_SCALE); //Normalized Gaussian mask design, 11*11, s.d. 1.5 Double weights[WEIGHTING_SIZE][WEIGHTING_SIZE]; { Double coeffSum=0.0; for(Int y=0; y original[MAX_MSSSIM_SCALE]; std::vector recon[MAX_MSSSIM_SCALE]; for(UInt scale=0; scale> scale; const Int scaledWidth = width >> scale; original[scale].resize(scaledHeight*scaledWidth, Double(0)); recon[scale].resize(scaledHeight*scaledWidth, Double(0)); } // Initial [0] arrays to be a copy of the source data (but stored in array "Double", not Pel array). for(Int y=0; y> scale; const Int scaledWidth = width >> scale; for(Int y=0; y> scale; const Int scaledWidth = width >> scale; const Int blocksPerRow = scaledWidth-WEIGHTING_SIZE+1; const Int blocksPerColumn = scaledHeight-WEIGHTING_SIZE+1; const Int totalBlocks = blocksPerRow*blocksPerColumn; Double meanSSIM= 0.0; for(Int blockIndexY=0; blockIndexYgetPicSym()->getSPS(); TComPic *apcPicOrgFields[2]={pcPicOrgFirstField, pcPicOrgSecondField}; TComPicYuv *apcPicRecFields[2]={pcPicRecFirstField, pcPicRecSecondField}; TComPicYuv cscd[2 /* first/second field */]; if (conversion!=IPCOLOURSPACE_UNCHANGED) { for(UInt fieldNum=0; fieldNum<2; fieldNum++) { TComPicYuv &reconField=*(apcPicRecFields[fieldNum]); cscd[fieldNum].createWithoutCUInfo(reconField.getWidth(COMPONENT_Y), reconField.getHeight(COMPONENT_Y), reconField.getChromaFormat() ); TVideoIOYuv::ColourSpaceConvert(reconField, cscd[fieldNum], conversion, false); apcPicRecFields[fieldNum]=cscd+fieldNum; } } //===== calculate PSNR ===== assert(apcPicRecFields[0]->getChromaFormat()==apcPicRecFields[1]->getChromaFormat()); const UInt numValidComponents=apcPicRecFields[0]->getNumberValidComponents(); const Bool useTrueOrg = conversion != IPCOLOURSPACE_UNCHANGED || m_pcCfg->getGopBasedTemporalFilterEnabled(); if (outputLogCtrl.printXPSNR && apcPicRecFields[0]->getChromaFormat() != CHROMA_400 && apcPicRecFields[1]->getChromaFormat() != CHROMA_400) { // For interlace images, we need to scan the two fields independently Pel* pOrg[MAX_NUM_COMPONENT]; Double dWeightPel[MAX_NUM_COMPONENT]; Int iWeightSize[MAX_NUM_COMPONENT] = {1, 1, 1}; Pel* pRec[MAX_NUM_COMPONENT]; Int iOrgStride[MAX_NUM_COMPONENT], iRecStride[MAX_NUM_COMPONENT]; Int iWidth[MAX_NUM_COMPONENT], iHeight[MAX_NUM_COMPONENT], iSize[MAX_NUM_COMPONENT]; UInt64 uiSSDtemp[MAX_NUM_COMPONENT]; UInt uiShiftWidth[MAX_NUM_COMPONENT], uiShiftHeight[MAX_NUM_COMPONENT]; Intermediate_Int iDiff; Double dSSDtemp = 0.0; Double fWValue = 0.0; for(UInt fieldNum=0; fieldNum<2; fieldNum++) { TComPic *pcPic=apcPicOrgFields[fieldNum]; TComPicYuv *pcPicD=apcPicRecFields[fieldNum]; TComPicYuv *pOrgPicYuv = useTrueOrg ? pcPic ->getPicYuvTrueOrg() : pcPic ->getPicYuvOrg(); for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); iOrgStride[ch] = pOrgPicYuv->getStride(ch); iRecStride[ch] = pcPicD->getStride(ch); iWidth[ch] = pcPicD->getWidth (ch) - (m_pcEncTop->getSourcePadding(0) >> pcPic->getComponentScaleX(ch)); iHeight[ch] = pcPicD->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> 1) >> pcPic->getComponentScaleY(ch)); iSize[ch] = iWidth[ch]*iHeight[ch]; uiSSDtemp[ch] = 0; uiShiftWidth[ch] = (ch == COMPONENT_Y || pcPicD->getChromaFormat() == CHROMA_444) ? 0 : 1; uiShiftHeight[ch] = (ch == COMPONENT_Y || pcPicD->getChromaFormat() == CHROMA_444 || pcPicD->getChromaFormat() == CHROMA_422) ? 0 : 1; dWeightPel[ch] = m_pcCfg->getXPSNRWeight(ch); pOrg[ch] = pOrgPicYuv->getAddr(ch); pRec[ch] = pcPicD->getAddr(ch); } std::vector vecSSEChroma(iSize[COMPONENT_Cb], Double(0)); for(Int y = 0, t= 0; y < iHeight[COMPONENT_Cb]; y++ ) { for(Int x = 0; x < iWidth[COMPONENT_Cb]; x++, t++) { UInt64 uiSE_cb, uiSE_cr; iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Cb][x] - (Intermediate_Int)pRec[COMPONENT_Cb][x] ); uiSE_cb = iDiff * iDiff; iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Cr][x] - (Intermediate_Int)pRec[COMPONENT_Cr][x] ); uiSE_cr = iDiff * iDiff; uiSSDtemp[COMPONENT_Cb] += uiSE_cb; uiSSDtemp[COMPONENT_Cr] += uiSE_cr; vecSSEChroma[t] = dWeightPel[COMPONENT_Cb] * (Double) uiSE_cb + dWeightPel[COMPONENT_Cr] * (Double) uiSE_cr; } pOrg[COMPONENT_Cb] += iOrgStride[COMPONENT_Cb]; pRec[COMPONENT_Cb] += iRecStride[COMPONENT_Cb]; pOrg[COMPONENT_Cr] += iOrgStride[COMPONENT_Cr]; pRec[COMPONENT_Cr] += iRecStride[COMPONENT_Cr]; } for(Int y = 0; y < iHeight[COMPONENT_Y]; y++ ) { UInt y_step_chroma = (y >> uiShiftHeight[COMPONENT_Cb]) * iWidth[COMPONENT_Cb]; for(Int x = 0; x < iWidth[COMPONENT_Y]; x++) { UInt64 uiSE_y; UInt x_step_chroma = (x >> uiShiftWidth[COMPONENT_Cb]); iDiff = (Intermediate_Int)( (Intermediate_Int)pOrg[COMPONENT_Y][x] - (Intermediate_Int)pRec[COMPONENT_Y][x] ); uiSE_y = iDiff * iDiff; uiSSDtemp[COMPONENT_Y] += uiSE_y; dSSDtemp += sqrt(dWeightPel[COMPONENT_Y] * (Double) uiSE_y + vecSSEChroma[y_step_chroma+x_step_chroma]); } pOrg[COMPONENT_Y] += iOrgStride[COMPONENT_Y]; pRec[COMPONENT_Y] += iRecStride[COMPONENT_Y]; } for( Int chan = 0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); const UInt maxval = 255 << (sps.getBitDepth(toChannelType(ch)) - 8); const Double fRefValue = (Double) maxval * maxval * iSize[ch]; result.psnr[ch] = ( uiSSDtemp[ch] ? 10.0 * log10( fRefValue / (Double)uiSSDtemp[ch] ) : 999.99 ); result.MSEyuvframe[ch] = (Double)uiSSDtemp[ch]/(iSize[ch]); fWValue += (Double) iWeightSize[ch] * (Double) iSize[ch]; } } const Double maxval = 255 << (sps.getBitDepth(toChannelType(COMPONENT_Y)) - 8); fWValue = Double( maxval * fWValue); result.xpsnr = dSSDtemp ? 20.0 * log10( fWValue / dSSDtemp) : 999.99; } else { for(Int chan=0; changetWidth(ch)==apcPicRecFields[1]->getWidth(ch)); assert(apcPicRecFields[0]->getHeight(ch)==apcPicRecFields[1]->getHeight(ch)); UInt64 uiSSDtemp=0; const Int iWidth = apcPicRecFields[0]->getWidth (ch) - (m_pcEncTop->getSourcePadding(0) >> apcPicRecFields[0]->getComponentScaleX(ch)); const Int iHeight = apcPicRecFields[0]->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> 1) >> apcPicRecFields[0]->getComponentScaleY(ch)); Int iSize = iWidth*iHeight; for(UInt fieldNum=0; fieldNum<2; fieldNum++) { TComPic *pcPic=apcPicOrgFields[fieldNum]; TComPicYuv *pcPicD=apcPicRecFields[fieldNum]; const Pel* pOrg = useTrueOrg ? pcPic ->getPicYuvTrueOrg()->getAddr(ch) : pcPic ->getPicYuvOrg()->getAddr(ch); Pel* pRec = pcPicD->getAddr(ch); const Int iStride = pcPicD->getStride(ch); for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] ); uiSSDtemp += iDiff * iDiff; } pOrg += iStride; pRec += iStride; } } const Int maxval = 255 << (sps.getBitDepth(toChannelType(ch)) - 8); const Double fRefValue = (Double) maxval * maxval * iSize*2; result.psnr[ch] = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 ); result.MSEyuvframe[ch] = (Double)uiSSDtemp/(iSize*2); } } //===== calculate MS-SSIM ===== if (outputLogCtrl.printMSSSIM) { for(Int chan=0; changetWidth(ch) ==apcPicRecFields[1]->getWidth(ch) ); assert(apcPicRecFields[0]->getHeight(ch)==apcPicRecFields[1]->getHeight(ch)); Double sumOverFieldsMSSSIM = 0.0; const Int width = apcPicRecFields[0]->getWidth (ch) - ( m_pcEncTop->getSourcePadding(0) >> apcPicRecFields[0]->getComponentScaleX(ch)); const Int height = apcPicRecFields[0]->getHeight(ch) - ((m_pcEncTop->getSourcePadding(1) >> 1) >> apcPicRecFields[0]->getComponentScaleY(ch)); for(UInt fieldNum=0; fieldNum<2; fieldNum++) { TComPic *pcPic = apcPicOrgFields[fieldNum]; TComPicYuv *pcPicD = apcPicRecFields[fieldNum]; const Pel* pOrg = useTrueOrg ? pcPic ->getPicYuvTrueOrg()->getAddr(ch) : pcPic ->getPicYuvOrg()->getAddr(ch); const Int orgStride = useTrueOrg ? pcPic ->getPicYuvTrueOrg()->getStride(ch) : pcPic ->getPicYuvOrg()->getStride(ch); Pel* pRec = pcPicD->getAddr(ch); const Int recStride = pcPicD->getStride(ch); const UInt bitDepth = sps.getBitDepth(toChannelType(ch)); sumOverFieldsMSSSIM += xCalculateMSSSIM (pOrg, orgStride, pRec, recStride, width, height, bitDepth); } result.MSSSIM[ch] = sumOverFieldsMSSSIM/2; } } result.bits = 0; // the number of bits for the pair is not calculated here - instead the overall total is used elsewhere. //===== add PSNR ===== m_gcAnalyzeAll_in.addResult (result); *PSNR_Y = result.psnr[COMPONENT_Y]; printf("\n Interlaced frame %d: [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", pcPicOrgSecondField->getPOC()/2 , result.psnr[COMPONENT_Y], result.psnr[COMPONENT_Cb], result.psnr[COMPONENT_Cr] ); if (outputLogCtrl.printHexPerPOCPSNRs) { uint64_t xPsnr[MAX_NUM_COMPONENT]; for (int i = 0; i < MAX_NUM_COMPONENT; i++) { copy(reinterpret_cast(&result.psnr[i]), reinterpret_cast(&result.psnr[i]) + sizeof(result.psnr[i]), reinterpret_cast(&xPsnr[i])); } printf(" [xY %16" PRIx64 " xU %16" PRIx64 " xv %16" PRIx64 "]", xPsnr[COMPONENT_Y], xPsnr[COMPONENT_Cb], xPsnr[COMPONENT_Cr]); } if (outputLogCtrl.printMSSSIM) { printf(" [MS-SSIM Y %1.6lf U %1.6lf V %1.6lf]", result.MSSSIM[COMPONENT_Y], result.MSSSIM[COMPONENT_Cb], result.MSSSIM[COMPONENT_Cr] ); } if (outputLogCtrl.printFrameMSE) { printf(" [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", result.MSEyuvframe[COMPONENT_Y], result.MSEyuvframe[COMPONENT_Cb], result.MSEyuvframe[COMPONENT_Cr] ); } for(UInt fieldNum=0; fieldNum<2; fieldNum++) { cscd[fieldNum].destroy(); } } /** Function for deciding the nal_unit_type. * \param pocCurr POC of the current picture * \param lastIDR POC of the last IDR picture * \param isField true to indicate field coding * \returns the NAL unit type of the picture * This function checks the configuration and returns the appropriate nal_unit_type for the picture. */ NalUnitType TEncGOP::getNalUnitType(Int pocCurr, Int lastIDR, Bool isField) { if (pocCurr == 0) { return NAL_UNIT_CODED_SLICE_IDR_W_RADL; } if(m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pocCurr == 1) { // to avoid the picture becoming an IRAP return NAL_UNIT_CODED_SLICE_TRAIL_R; } if(m_pcCfg->getDecodingRefreshType() != 3 && (pocCurr - isField) % m_pcCfg->getIntraPeriod() == 0) { if (m_pcCfg->getDecodingRefreshType() == 1) { return NAL_UNIT_CODED_SLICE_CRA; } else if (m_pcCfg->getDecodingRefreshType() == 2) { return NAL_UNIT_CODED_SLICE_IDR_W_RADL; } } if(m_pocCRA>0) { if(pocCurr0) { if (pocCurr < lastIDR) { return NAL_UNIT_CODED_SLICE_RADL_R; } } return NAL_UNIT_CODED_SLICE_TRAIL_R; } Double TEncGOP::xCalculateRVM() { Double dRVM = 0; if( m_pcCfg->getGOPSize() == 1 && m_pcCfg->getIntraPeriod() != 1 && m_pcCfg->getFramesToBeEncoded() > RVM_VCEGAM10_M * 2 ) { // calculate RVM only for lowdelay configurations std::vector vRL , vB; size_t N = m_vRVM_RP.size(); vRL.resize( N ); vB.resize( N ); Int i; Double dRavg = 0 , dBavg = 0; vB[RVM_VCEGAM10_M] = 0; for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ ) { vRL[i] = 0; for( Int j = i - RVM_VCEGAM10_M ; j <= i + RVM_VCEGAM10_M - 1 ; j++ ) { vRL[i] += m_vRVM_RP[j]; } vRL[i] /= ( 2 * RVM_VCEGAM10_M ); vB[i] = vB[i-1] + m_vRVM_RP[i] - vRL[i]; dRavg += m_vRVM_RP[i]; dBavg += vB[i]; } dRavg /= ( N - 2 * RVM_VCEGAM10_M ); dBavg /= ( N - 2 * RVM_VCEGAM10_M ); Double dSigamB = 0; for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ ) { Double tmp = vB[i] - dBavg; dSigamB += tmp * tmp; } dSigamB = sqrt( dSigamB / ( N - 2 * RVM_VCEGAM10_M ) ); Double f = sqrt( 12.0 * ( RVM_VCEGAM10_M - 1 ) / ( RVM_VCEGAM10_M + 1 ) ); dRVM = dSigamB / dRavg * f; } return( dRVM ); } /** Attaches the input bitstream to the stream in the output NAL unit Updates rNalu to contain concatenated bitstream. rpcBitstreamRedirect is cleared at the end of this function call. * \param codedSliceData contains the coded slice data (bitstream) to be concatenated to rNalu * \param rNalu target NAL unit */ Void TEncGOP::xAttachSliceDataToNalUnit (OutputNALUnit& rNalu, TComOutputBitstream* codedSliceData) { // Byte-align rNalu.m_Bitstream.writeByteAlignment(); // Slice header byte-alignment // Perform bitstream concatenation if (codedSliceData->getNumberOfWrittenBits() > 0) { rNalu.m_Bitstream.addSubstream(codedSliceData); } m_pcEntropyCoder->setBitstream(&rNalu.m_Bitstream); codedSliceData->clear(); } // Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt, // and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value Void TEncGOP::arrangeLongtermPicturesInRPS(TComSlice *pcSlice, TComList& rcListPic) { if(pcSlice->getRPS()->getNumberOfLongtermPictures() == 0) { return; } // we can only modify the local RPS! assert (pcSlice->getRPSidx()==-1); TComReferencePictureSet *rps = pcSlice->getLocalRPS(); // Arrange long-term reference pictures in the correct order of LSB and MSB, // and assign values for pocLSBLT and MSB present flag Int longtermPicsPoc[MAX_NUM_REF_PICS], longtermPicsLSB[MAX_NUM_REF_PICS], indices[MAX_NUM_REF_PICS]; Int longtermPicsMSB[MAX_NUM_REF_PICS]; Bool mSBPresentFlag[MAX_NUM_REF_PICS]; ::memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc)); // Store POC values of LTRP ::memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB)); // Store POC LSB values of LTRP ::memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB)); // Store POC LSB values of LTRP ::memset(indices , 0, sizeof(indices)); // Indices to aid in tracking sorted LTRPs ::memset(mSBPresentFlag , 0, sizeof(mSBPresentFlag)); // Indicate if MSB needs to be present // Get the long-term reference pictures Int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures(); Int i, ctr = 0; Int maxPicOrderCntLSB = 1 << pcSlice->getSPS()->getBitsForPOC(); for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { longtermPicsPoc[ctr] = rps->getPOC(i); // LTRP POC longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB indices[ctr] = i; longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr]; } Int numLongPics = rps->getNumberOfLongtermPictures(); assert(ctr == numLongPics); // Arrange pictures in decreasing order of MSB; for(i = 0; i < numLongPics; i++) { for(Int j = 0; j < numLongPics - 1; j++) { if(longtermPicsMSB[j] < longtermPicsMSB[j+1]) { std::swap(longtermPicsPoc[j], longtermPicsPoc[j+1]); std::swap(longtermPicsLSB[j], longtermPicsLSB[j+1]); std::swap(longtermPicsMSB[j], longtermPicsMSB[j+1]); std::swap(indices[j] , indices[j+1] ); } } } for(i = 0; i < numLongPics; i++) { // Check if MSB present flag should be enabled. // Check if the buffer contains any pictures that have the same LSB. TComList::iterator iterPic = rcListPic.begin(); TComPic* pcPic; while ( iterPic != rcListPic.end() ) { pcPic = *iterPic; if( (getLSB(pcPic->getPOC(), maxPicOrderCntLSB) == longtermPicsLSB[i]) && // Same LSB (pcPic->getSlice(0)->isReferenced()) && // Reference picture (pcPic->getPOC() != longtermPicsPoc[i]) ) // Not the LTRP itself { mSBPresentFlag[i] = true; break; } iterPic++; } } // tempArray for usedByCurr flag Bool tempArray[MAX_NUM_REF_PICS]; ::memset(tempArray, 0, sizeof(tempArray)); for(i = 0; i < numLongPics; i++) { tempArray[i] = rps->getUsed(indices[i]); } // Now write the final values; ctr = 0; Int currMSB = 0, currLSB = 0; // currPicPoc = currMSB + currLSB currLSB = getLSB(pcSlice->getPOC(), maxPicOrderCntLSB); currMSB = pcSlice->getPOC() - currLSB; for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { rps->setPOC (i, longtermPicsPoc[ctr]); rps->setDeltaPOC (i, - pcSlice->getPOC() + longtermPicsPoc[ctr]); rps->setUsed (i, tempArray[ctr]); rps->setPocLSBLT (i, longtermPicsLSB[ctr]); rps->setDeltaPocMSBCycleLT (i, (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB); rps->setDeltaPocMSBPresentFlag(i, mSBPresentFlag[ctr]); assert(rps->getDeltaPocMSBCycleLT(i) >= 0); // Non-negative value } for(i = rps->getNumberOfPictures() - 1, ctr = 1; i >= offset; i--, ctr++) { for(Int j = rps->getNumberOfPictures() - 1 - ctr; j >= offset; j--) { // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we // don't have to check the MSB present flag values for this constraint. assert( rps->getPOC(i) != rps->getPOC(j) ); // If assert fails, LTRP entry repeated in RPS!!! } } } Void TEncGOP::applyDeblockingFilterMetric( TComPic* pcPic, UInt uiNumSlices ) { TComPicYuv* pcPicYuvRec = pcPic->getPicYuvRec(); Pel* Rec = pcPicYuvRec->getAddr(COMPONENT_Y); Pel* tempRec = Rec; Int stride = pcPicYuvRec->getStride(COMPONENT_Y); UInt log2maxTB = pcPic->getSlice(0)->getSPS()->getQuadtreeTULog2MaxSize(); UInt maxTBsize = (1<getWidth(COMPONENT_Y); const UInt picHeight = pcPicYuvRec->getHeight(COMPONENT_Y); const UInt noCol = (picWidth>>log2maxTB); const UInt noRows = (picHeight>>log2maxTB); assert(noCol > 1); assert(noRows > 1); std::vector colSAD(noCol, UInt64(0)); std::vector rowSAD(noRows, UInt64(0)); UInt colIdx = 0; UInt rowIdx = 0; Pel p0, p1, p2, q0, q1, q2; Int qp = pcPic->getSlice(0)->getSliceQp(); const Int bitDepthLuma=pcPic->getSlice(0)->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA); Int bitdepthScale = 1 << (bitDepthLuma-8); Int beta = TComLoopFilter::getBeta( qp ) * bitdepthScale; const Int thr2 = (beta>>2); const Int thr1 = 2*bitdepthScale; UInt a = 0; if (maxTBsize > minBlockArtSize) { // Analyze vertical artifact edges for(Int c = maxTBsize; c < picWidth; c += maxTBsize) { for(Int r = 0; r < picHeight; r++) { p2 = Rec[c-3]; p1 = Rec[c-2]; p0 = Rec[c-1]; q0 = Rec[c]; q1 = Rec[c+1]; q2 = Rec[c+2]; a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1); if ( thr1 < a && a < thr2) { colSAD[colIdx] += abs(p0 - q0); } Rec += stride; } colIdx++; Rec = tempRec; } // Analyze horizontal artifact edges for(Int r = maxTBsize; r < picHeight; r += maxTBsize) { for(Int c = 0; c < picWidth; c++) { p2 = Rec[c + (r-3)*stride]; p1 = Rec[c + (r-2)*stride]; p0 = Rec[c + (r-1)*stride]; q0 = Rec[c + r*stride]; q1 = Rec[c + (r+1)*stride]; q2 = Rec[c + (r+2)*stride]; a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1); if (thr1 < a && a < thr2) { rowSAD[rowIdx] += abs(p0 - q0); } } rowIdx++; } } UInt64 colSADsum = 0; UInt64 rowSADsum = 0; for(Int c = 0; c < noCol-1; c++) { colSADsum += colSAD[c]; } for(Int r = 0; r < noRows-1; r++) { rowSADsum += rowSAD[r]; } colSADsum <<= 10; rowSADsum <<= 10; colSADsum /= (noCol-1); colSADsum /= picHeight; rowSADsum /= (noRows-1); rowSADsum /= picWidth; UInt64 avgSAD = ((colSADsum + rowSADsum)>>1); avgSAD >>= (bitDepthLuma-8); if ( avgSAD > 2048 ) { avgSAD >>= 9; Int offset = Clip3(2,6,(Int)avgSAD); for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(true); pcPic->getSlice(i)->setDeblockingFilterDisable(false); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( offset ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( offset ); } } else { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(false); pcPic->getSlice(i)->setDeblockingFilterDisable( pcPic->getSlice(i)->getPPS()->getPPSDeblockingFilterDisabledFlag() ); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterBetaOffsetDiv2() ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterTcOffsetDiv2() ); } } } Void TEncGOP::applyDeblockingFilterParameterSelection( TComPic* pcPic, const UInt numSlices, const Int gopID ) { enum DBFltParam { DBFLT_PARAM_AVAILABLE = 0, DBFLT_DISABLE_FLAG, DBFLT_BETA_OFFSETD2, DBFLT_TC_OFFSETD2, //NUM_DBFLT_PARAMS }; const Int MAX_BETA_OFFSET = 3; const Int MIN_BETA_OFFSET = -3; const Int MAX_TC_OFFSET = 3; const Int MIN_TC_OFFSET = -3; TComPicYuv* pcPicYuvRec = pcPic->getPicYuvRec(); TComPicYuv* pcPicYuvOrg = pcPic ->getPicYuvOrg(); const Int currQualityLayer = (pcPic->getSlice(0)->getSliceType() != I_SLICE) ? m_pcCfg->getGOPEntry(gopID).m_temporalId+1 : 0; assert(currQualityLayer create( m_pcEncTop->getSourceWidth(), m_pcEncTop->getSourceHeight(), m_pcEncTop->getChromaFormatIdc(), pcPic->getSlice(0)->getSPS()->getMaxCUWidth(), pcPic->getSlice(0)->getSPS()->getMaxCUHeight(), pcPic->getSlice(0)->getSPS()->getMaxTotalCUDepth(),true ); memset(m_DBParam, 0, sizeof(m_DBParam)); } //preserve current reconstruction pcPicYuvRec->copyToPic(m_pcDeblockingTempPicYuv); const Bool bNoFiltering = m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] && m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]==false /*&& pcPic->getTLayer()==0*/; const Int maxBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]+1) : MAX_BETA_OFFSET; const Int minBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]-1) : MIN_BETA_OFFSET; const Int maxTcOffsetDiv2 = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]+2) : MAX_TC_OFFSET; const Int minTcOffsetDiv2 = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]-2) : MIN_TC_OFFSET; UInt64 distBetaPrevious = std::numeric_limits::max(); UInt64 distMin = std::numeric_limits::max(); Bool bDBFilterDisabledBest = true; Int betaOffsetDiv2Best = 0; Int tcOffsetDiv2Best = 0; for(Int betaOffsetDiv2=maxBetaOffsetDiv2; betaOffsetDiv2>=minBetaOffsetDiv2; betaOffsetDiv2--) { UInt64 distTcMin = std::numeric_limits::max(); for(Int tcOffsetDiv2=maxTcOffsetDiv2; tcOffsetDiv2 >= minTcOffsetDiv2; tcOffsetDiv2--) { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(true); pcPic->getSlice(i)->setDeblockingFilterDisable(false); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( betaOffsetDiv2 ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( tcOffsetDiv2 ); } m_pcDeblockingTempPicYuv->copyToPic(pcPicYuvRec); // restore reconstruction m_pcLoopFilter->loopFilterPic( pcPic ); const UInt64 dist = xFindDistortionFrame(pcPicYuvOrg, pcPicYuvRec, pcPic->getPicSym()->getSPS().getBitDepths()); if(dist < distMin) { distMin = dist; bDBFilterDisabledBest = false; betaOffsetDiv2Best = betaOffsetDiv2; tcOffsetDiv2Best = tcOffsetDiv2; } if(dist < distTcMin) { distTcMin = dist; } else if(tcOffsetDiv2 <-2) { break; } } if(betaOffsetDiv2<-1 && distTcMin >= distBetaPrevious) { break; } distBetaPrevious = distTcMin; } //update: m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] = 1; m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG] = bDBFilterDisabledBest; m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2] = betaOffsetDiv2Best; m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2] = tcOffsetDiv2Best; m_pcDeblockingTempPicYuv->copyToPic(pcPicYuvRec); //restore reconstruction if(bDBFilterDisabledBest) { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(true); pcPic->getSlice(i)->setDeblockingFilterDisable(true); } } else if(betaOffsetDiv2Best ==pcPic->getSlice(0)->getPPS()->getDeblockingFilterBetaOffsetDiv2() && tcOffsetDiv2Best==pcPic->getSlice(0)->getPPS()->getDeblockingFilterTcOffsetDiv2()) { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(false); pcPic->getSlice(i)->setDeblockingFilterDisable( pcPic->getSlice(i)->getPPS()->getPPSDeblockingFilterDisabledFlag() ); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterBetaOffsetDiv2() ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterTcOffsetDiv2() ); } } else { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(true); pcPic->getSlice(i)->setDeblockingFilterDisable( false ); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2(betaOffsetDiv2Best); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2(tcOffsetDiv2Best); } } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncGOP.h000066400000000000000000000257721442026013100177660ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncGOP.h \brief GOP encoder class (header) */ #ifndef __TENCGOP__ #define __TENCGOP__ #include #include #include "TLibCommon/TComList.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComBitCounter.h" #include "TLibCommon/TComLoopFilter.h" #include "TLibCommon/AccessUnit.h" #include "TEncSampleAdaptiveOffset.h" #include "TEncSlice.h" #include "TEncEntropy.h" #include "TEncCavlc.h" #include "TEncSbac.h" #include "SEIwrite.h" #include "SEIEncoder.h" #if EXTENSION_360_VIDEO #include "TAppEncHelper360/TExt360EncGop.h" #endif #if JVET_X0048_X0103_FILM_GRAIN #include "TLibCommon/SEIFilmGrainAnalyzer.h" #endif #include "TEncAnalyze.h" #include "TEncRateCtrl.h" #include //! \ingroup TLibEncoder //! \{ class TEncTop; // ==================================================================================================================== // Class definition // ==================================================================================================================== class TEncGOP { class DUData { public: DUData() :accumBitsDU(0) ,accumNalsDU(0) {}; Int accumBitsDU; Int accumNalsDU; }; private: TEncAnalyze m_gcAnalyzeAll; TEncAnalyze m_gcAnalyzeI; TEncAnalyze m_gcAnalyzeP; TEncAnalyze m_gcAnalyzeB; TEncAnalyze m_gcAnalyzeAll_in; #if EXTENSION_360_VIDEO TExt360EncGop m_ext360; public: TExt360EncGop &getExt360Data() { return m_ext360; } private: #endif // Data Bool m_bLongtermTestPictureHasBeenCoded; Bool m_bLongtermTestPictureHasBeenCoded2; UInt m_numLongTermRefPicSPS; UInt m_ltRefPicPocLsbSps[MAX_NUM_LONG_TERM_REF_PICS]; Bool m_ltRefPicUsedByCurrPicFlag[MAX_NUM_LONG_TERM_REF_PICS]; Int m_iLastIDR; Int m_RASPOCforResetEncoder; // an IDR POC number, after which the next POC (in output order) will be reset. If MAX_INT, then no reset is pending. Int m_iGopSize; Int m_iNumPicCoded; Bool m_bFirst; Int m_iLastRecoveryPicPOC; // Access channel TEncTop* m_pcEncTop; TEncCfg* m_pcCfg; TEncSlice* m_pcSliceEncoder; TComList* m_pcListPic; TEncEntropy* m_pcEntropyCoder; TEncCavlc* m_pcCavlcCoder; TEncSbac* m_pcSbacCoder; TEncBinCABAC* m_pcBinCABAC; TComLoopFilter* m_pcLoopFilter; SEIWriter m_seiWriter; #if JVET_X0048_X0103_FILM_GRAIN FGAnalyser m_FGAnalyser; #endif //--Adaptive Loop filter TEncSampleAdaptiveOffset* m_pcSAO; TEncRateCtrl* m_pcRateCtrl; // indicate sequence first Bool m_bSeqFirst; // clean decoding refresh Bool m_bRefreshPending; Int m_pocCRA; NalUnitType m_associatedIRAPType; Int m_associatedIRAPPOC; std::vector m_vRVM_RP; UInt m_lastBPSEI; UInt m_totalCoded; Bool m_bufferingPeriodSEIPresentInAU; SEIEncoder m_seiEncoder; TComPicYuv* m_pcDeblockingTempPicYuv; Int m_DBParam[MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS][4]; //[layer_id][0: available; 1: bDBDisabled; 2: Beta Offset Div2; 3: Tc Offset Div2;] public: TEncGOP(); virtual ~TEncGOP(); Void create (); Void destroy (); Void init ( TEncTop* pcTEncTop ); Void compressGOP ( Int iPOCLast, Int iNumPicRcvd, TComList& rcListPic, TComList& rcListPicYuvRec, std::list& accessUnitsInGOP, Bool isField, Bool isTff, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl ); Void xAttachSliceDataToNalUnit (OutputNALUnit& rNalu, TComOutputBitstream* pcBitstreamRedirect); Int getGOPSize() { return m_iGopSize; } TComList* getListPic() { return m_pcListPic; } Void printOutSummary ( UInt uiNumAllPicCoded, Bool isField, const TEncAnalyze::OutputLogControl &outputLogCtrl, const BitDepths &bitDepths ); Void preLoopFilterPicAll ( TComPic* pcPic, UInt64& ruiDist ); TEncSlice* getSliceEncoder() { return m_pcSliceEncoder; } NalUnitType getNalUnitType( Int pocCurr, Int lastIdr, Bool isField ); Void arrangeLongtermPicturesInRPS(TComSlice *, TComList& ); TEncAnalyze& getAnalyzeAllData() { return m_gcAnalyzeAll; } TEncAnalyze& getAnalyzeIData() { return m_gcAnalyzeI; } TEncAnalyze& getAnalyzePData() { return m_gcAnalyzeP; } TEncAnalyze& getAnalyzeBData() { return m_gcAnalyzeB; } #if MCTS_EXTRACTION Void generateVPS_RBSP(TComBitIf* rbsp, const TComVPS *vps); Void generateSPS_RBSP(TComBitIf* rbsp, const TComSPS *sps); Void generatePPS_RBSP(TComBitIf* rbsp, const TComPPS *pps); #endif protected: TEncRateCtrl* getRateCtrl() { return m_pcRateCtrl; } protected: Void xInitGOP ( Int iPOCLast, Int iNumPicRcvd, Bool isField ); Void xGetBuffer ( TComList& rcListPic, TComList& rcListPicYuvRecOut, Int iNumPicRcvd, Int iTimeOffset, TComPic*& rpcPic, TComPicYuv*& rpcPicYuvRecOut, Int pocCurr, Bool isField ); Void xCalculateAddPSNRs ( const Bool isField, const Bool isFieldTopFieldFirst, const Int iGOPid, TComPic* pcPic, const AccessUnit&accessUnit, TComList &rcListPic, Double dEncTime, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl, Double* PSNR_Y ); Void xCalculateAddPSNR ( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit&, Double dEncTime, const InputColourSpaceConversion ip_conversion, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl, Double* PSNR_Y ); Void xCalculateInterlacedAddPSNR( TComPic* pcPicOrgFirstField, TComPic* pcPicOrgSecondField, TComPicYuv* pcPicRecFirstField, TComPicYuv* pcPicRecSecondField, const InputColourSpaceConversion snr_conversion, const TEncAnalyze::OutputLogControl &outputLogCtrl, Double* PSNR_Y ); Double xCalculateMSSSIM (const Pel *pOrg, const Int orgStride, const Pel* pRec, const Int recStride, const Int width, const Int height, const UInt bitDepth); UInt64 xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths); Double xCalculateRVM(); Void xWriteAccessUnitDelimiter (AccessUnit &accessUnit, TComSlice *slice); #if MCTS_EXTRACTION Void xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const TComVPS *vps, const TComSPS *sps, const TComPPS *pps); #else Void xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const TComSPS *sps, const TComPPS *pps); #endif Void xCreatePerPictureSEIMessages (Int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, TComSlice *slice); Void xCreatePictureTimingSEI (Int IRAPGOPid, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, SEIMessages& duInfoSeiMessages, TComSlice *slice, Bool isField, std::deque &duData); Void xUpdateDuData(AccessUnit &testAU, std::deque &duData); Void xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque &duData, const TComSPS *sps); Void xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI); Void xCreateScalableNestingSEI (SEIMessages& seiMessages, SEIMessages& nestedSeiMessages); Void xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps); Void xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps); Void xClearSEIs(SEIMessages& seiMessages, Bool deleteMessages); Void xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, Bool testWrite); Void xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque &duData); Void xWriteTrailingSEIMessages (SEIMessages& seiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps); Void xWriteDuSEIMessages (SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque &duData); Int xWriteVPS (AccessUnit &accessUnit, const TComVPS *vps); Int xWriteSPS (AccessUnit &accessUnit, const TComSPS *sps); Int xWritePPS (AccessUnit &accessUnit, const TComPPS *pps); Int xWriteParameterSets (AccessUnit &accessUnit, TComSlice *slice, const Bool bSeqFirst); Void applyDeblockingFilterMetric( TComPic* pcPic, UInt uiNumSlices ); Void applyDeblockingFilterParameterSelection( TComPic* pcPic, const UInt numSlices, const Int gopID ); };// END CLASS DEFINITION TEncGOP //! \} #endif // __TENCGOP__ HM-HM-18.0/source/Lib/TLibEncoder/TEncPic.cpp000066400000000000000000000126701442026013100204000ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncPic.cpp \brief class of picture which includes side information for encoder */ #include "TEncPic.h" //! \ingroup TLibEncoder //! \{ /** Constructor */ TEncQPAdaptationUnit::TEncQPAdaptationUnit() : m_dActivity(0.0) { } /** Destructor */ TEncQPAdaptationUnit::~TEncQPAdaptationUnit() { } /** Constructor */ TEncPicQPAdaptationLayer::TEncPicQPAdaptationLayer() : m_uiAQPartWidth(0) , m_uiAQPartHeight(0) , m_uiNumAQPartInWidth(0) , m_uiNumAQPartInHeight(0) , m_acTEncAQU(NULL) , m_dAvgActivity(0.0) { } /** Destructor */ TEncPicQPAdaptationLayer::~TEncPicQPAdaptationLayer() { destroy(); } /** Initialize member variables * \param iWidth Picture width * \param iHeight Picture height * \param uiAQPartWidth Width of unit block for analyzing local image characteristics * \param uiAQPartHeight Height of unit block for analyzing local image characteristics * \return Void */ Void TEncPicQPAdaptationLayer::create( Int iWidth, Int iHeight, UInt uiAQPartWidth, UInt uiAQPartHeight ) { m_uiAQPartWidth = uiAQPartWidth; m_uiAQPartHeight = uiAQPartHeight; m_uiNumAQPartInWidth = (iWidth + m_uiAQPartWidth-1) / m_uiAQPartWidth; m_uiNumAQPartInHeight = (iHeight + m_uiAQPartHeight-1) / m_uiAQPartHeight; m_acTEncAQU = new TEncQPAdaptationUnit[ m_uiNumAQPartInWidth * m_uiNumAQPartInHeight ]; } /** Clean up * \return Void */ Void TEncPicQPAdaptationLayer::destroy() { if (m_acTEncAQU) { delete[] m_acTEncAQU; m_acTEncAQU = NULL; } } /** Constructor */ TEncPic::TEncPic() : m_acAQLayer(NULL) , m_uiMaxAQDepth(0) { } /** Destructor */ TEncPic::~TEncPic() { destroy(); } /** Initialize member variables * \param sps reference to used SPS * \param pps reference to used PPS * \param uiMaxAdaptiveQPDepth Maximum depth of unit block for assigning QP adaptive to local image characteristics * \param bIsVirtual */ #if REDUCED_ENCODER_MEMORY Void TEncPic::create( const TComSPS &sps, const TComPPS &pps, UInt uiMaxAdaptiveQPDepth #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ) { TComPic::create( sps, pps, true, false #if SHUTTER_INTERVAL_SEI_PROCESSING , bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , bCreateFilteredSourcePicYuv #endif ); #else Void TEncPic::create( const TComSPS &sps, const TComPPS &pps, UInt uiMaxAdaptiveQPDepth, Bool bIsVirtual #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ) { TComPic::create( sps, pps, bIsVirtual #if SHUTTER_INTERVAL_SEI_PROCESSING , bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , bCreateFilteredSourcePicYuv #endif ); #endif const Int iWidth = sps.getPicWidthInLumaSamples(); const Int iHeight = sps.getPicHeightInLumaSamples(); const UInt uiMaxWidth = sps.getMaxCUWidth(); const UInt uiMaxHeight = sps.getMaxCUHeight(); m_uiMaxAQDepth = uiMaxAdaptiveQPDepth; if ( uiMaxAdaptiveQPDepth > 0 ) { m_acAQLayer = new TEncPicQPAdaptationLayer[ m_uiMaxAQDepth ]; for (UInt d = 0; d < m_uiMaxAQDepth; d++) { m_acAQLayer[d].create( iWidth, iHeight, uiMaxWidth>>d, uiMaxHeight>>d ); } } } //! Clean up Void TEncPic::destroy() { if (m_acAQLayer) { delete[] m_acAQLayer; m_acAQLayer = NULL; } TComPic::destroy(); } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncPic.h000066400000000000000000000117101442026013100200370ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncPic.h \brief class of picture which includes side information for encoder (header) */ #ifndef __TENCPIC__ #define __TENCPIC__ #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComPic.h" //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Unit block for storing image characteristics class TEncQPAdaptationUnit { private: Double m_dActivity; public: TEncQPAdaptationUnit(); ~TEncQPAdaptationUnit(); Void setActivity( Double d ) { m_dActivity = d; } Double getActivity() { return m_dActivity; } }; /// Local image characteristics for CUs on a specific depth class TEncPicQPAdaptationLayer { private: UInt m_uiAQPartWidth; UInt m_uiAQPartHeight; UInt m_uiNumAQPartInWidth; UInt m_uiNumAQPartInHeight; TEncQPAdaptationUnit* m_acTEncAQU; Double m_dAvgActivity; public: TEncPicQPAdaptationLayer(); virtual ~TEncPicQPAdaptationLayer(); Void create( Int iWidth, Int iHeight, UInt uiAQPartWidth, UInt uiAQPartHeight ); Void destroy(); UInt getAQPartWidth() { return m_uiAQPartWidth; } UInt getAQPartHeight() { return m_uiAQPartHeight; } UInt getNumAQPartInWidth() { return m_uiNumAQPartInWidth; } UInt getNumAQPartInHeight() { return m_uiNumAQPartInHeight; } UInt getAQPartStride() { return m_uiNumAQPartInWidth; } TEncQPAdaptationUnit* getQPAdaptationUnit() { return m_acTEncAQU; } Double getAvgActivity() { return m_dAvgActivity; } Void setAvgActivity( Double d ) { m_dAvgActivity = d; } }; /// Picture class including local image characteristics information for QP adaptation class TEncPic : public TComPic { private: TEncPicQPAdaptationLayer* m_acAQLayer; UInt m_uiMaxAQDepth; public: TEncPic(); virtual ~TEncPic(); #if REDUCED_ENCODER_MEMORY Void create( const TComSPS &sps, const TComPPS &pps, UInt uiMaxAdaptiveQPDepth #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ); #else Void create( const TComSPS &sps, const TComPPS &pps, UInt uiMaxAdaptiveQPDepth, Bool bIsVirtual /* = false*/ #if SHUTTER_INTERVAL_SEI_PROCESSING , const Bool bCreateForProcessedReconstruction #endif #if JVET_X0048_X0103_FILM_GRAIN , const Bool bCreateFilteredSourcePicYuv #endif ); #endif virtual Void destroy(); TEncPicQPAdaptationLayer* getAQLayer( UInt uiDepth ) { return &m_acAQLayer[uiDepth]; } UInt getMaxAQDepth() { return m_uiMaxAQDepth; } }; //! \} #endif // __TENCPIC__ HM-HM-18.0/source/Lib/TLibEncoder/TEncPreanalyzer.cpp000066400000000000000000000123631442026013100221600ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncPreanalyzer.cpp \brief source picture analyzer class */ #include #include #include "TEncPreanalyzer.h" using namespace std; //! \ingroup TLibEncoder //! \{ /** Constructor */ TEncPreanalyzer::TEncPreanalyzer() { } /** Destructor */ TEncPreanalyzer::~TEncPreanalyzer() { } /** Analyze source picture and compute local image characteristics used for QP adaptation * \param pcEPic Picture object to be analyzed * \return Void */ Void TEncPreanalyzer::xPreanalyze( TEncPic* pcEPic ) { TComPicYuv* pcPicYuv = pcEPic->getPicYuvOrg(); const Int iWidth = pcPicYuv->getWidth(COMPONENT_Y); const Int iHeight = pcPicYuv->getHeight(COMPONENT_Y); const Int iStride = pcPicYuv->getStride(COMPONENT_Y); for ( UInt d = 0; d < pcEPic->getMaxAQDepth(); d++ ) { const Pel* pLineY = pcPicYuv->getAddr(COMPONENT_Y); TEncPicQPAdaptationLayer* pcAQLayer = pcEPic->getAQLayer(d); const UInt uiAQPartWidth = pcAQLayer->getAQPartWidth(); const UInt uiAQPartHeight = pcAQLayer->getAQPartHeight(); TEncQPAdaptationUnit* pcAQU = pcAQLayer->getQPAdaptationUnit(); Double dSumAct = 0.0; for ( UInt y = 0; y < iHeight; y += uiAQPartHeight ) { const UInt uiCurrAQPartHeight = min(uiAQPartHeight, iHeight-y); for ( UInt x = 0; x < iWidth; x += uiAQPartWidth, pcAQU++ ) { const UInt uiCurrAQPartWidth = min(uiAQPartWidth, iWidth-x); const Pel* pBlkY = &pLineY[x]; UInt64 uiSum[4] = {0, 0, 0, 0}; UInt64 uiSumSq[4] = {0, 0, 0, 0}; UInt by = 0; for ( ; by < uiCurrAQPartHeight>>1; by++ ) { UInt bx = 0; for ( ; bx < uiCurrAQPartWidth>>1; bx++ ) { uiSum [0] += pBlkY[bx]; uiSumSq[0] += pBlkY[bx] * pBlkY[bx]; } for ( ; bx < uiCurrAQPartWidth; bx++ ) { uiSum [1] += pBlkY[bx]; uiSumSq[1] += pBlkY[bx] * pBlkY[bx]; } pBlkY += iStride; } for ( ; by < uiCurrAQPartHeight; by++ ) { UInt bx = 0; for ( ; bx < uiCurrAQPartWidth>>1; bx++ ) { uiSum [2] += pBlkY[bx]; uiSumSq[2] += pBlkY[bx] * pBlkY[bx]; } for ( ; bx < uiCurrAQPartWidth; bx++ ) { uiSum [3] += pBlkY[bx]; uiSumSq[3] += pBlkY[bx] * pBlkY[bx]; } pBlkY += iStride; } assert ((uiCurrAQPartWidth&1)==0); assert ((uiCurrAQPartHeight&1)==0); const UInt pixelWidthOfQuadrants = uiCurrAQPartWidth >>1; const UInt pixelHeightOfQuadrants = uiCurrAQPartHeight>>1; const UInt numPixInAQPart = pixelWidthOfQuadrants * pixelHeightOfQuadrants; Double dMinVar = DBL_MAX; if (numPixInAQPart!=0) { for ( Int i=0; i<4; i++) { const Double dAverage = Double(uiSum[i]) / numPixInAQPart; const Double dVariance = Double(uiSumSq[i]) / numPixInAQPart - dAverage * dAverage; dMinVar = min(dMinVar, dVariance); } } else { dMinVar = 0.0; } const Double dActivity = 1.0 + dMinVar; pcAQU->setActivity( dActivity ); dSumAct += dActivity; } pLineY += iStride * uiCurrAQPartHeight; } const Double dAvgAct = dSumAct / (pcAQLayer->getNumAQPartInWidth() * pcAQLayer->getNumAQPartInHeight()); pcAQLayer->setAvgActivity( dAvgAct ); } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncPreanalyzer.h000066400000000000000000000046761442026013100216350ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncPreanalyzer.h \brief source picture analyzer class (header) */ #ifndef __TENCPREANALYZER__ #define __TENCPREANALYZER__ #include "TEncPic.h" //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// Source picture analyzer class class TEncPreanalyzer { public: TEncPreanalyzer(); virtual ~TEncPreanalyzer(); Void xPreanalyze( TEncPic* pcPic ); }; //! \} #endif // __TENCPREANALYZER__ HM-HM-18.0/source/Lib/TLibEncoder/TEncRateCtrl.cpp000066400000000000000000001475421442026013100214140ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncRateCtrl.cpp \brief Rate control manager class */ #include "TEncRateCtrl.h" #include "../TLibCommon/TComPic.h" #include "../TLibCommon/TComChromaFormat.h" #include using namespace std; //sequence level TEncRCSeq::TEncRCSeq() { m_totalFrames = 0; m_targetRate = 0; m_frameRate = 0; m_targetBits = 0; m_GOPSize = 0; #if JVET_Y0105_SW_AND_QDF m_intraPeriod = 0; #endif m_picWidth = 0; m_picHeight = 0; m_LCUWidth = 0; m_LCUHeight = 0; m_numberOfLevel = 0; m_numberOfLCU = 0; m_averageBits = 0; m_bitsRatio = NULL; m_GOPID2Level = NULL; m_picPara = NULL; m_LCUPara = NULL; m_numberOfPixel = 0; m_framesLeft = 0; m_bitsLeft = 0; m_useLCUSeparateModel = false; m_adaptiveBit = 0; m_lastLambda = 0.0; } TEncRCSeq::~TEncRCSeq() { destroy(); } #if JVET_Y0105_SW_AND_QDF Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int intraPeriod, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ) #else Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ) #endif { destroy(); m_totalFrames = totalFrames; m_targetRate = targetBitrate; m_frameRate = frameRate; m_GOPSize = GOPSize; #if JVET_Y0105_SW_AND_QDF m_intraPeriod = intraPeriod; #endif m_picWidth = picWidth; m_picHeight = picHeight; m_LCUWidth = LCUWidth; m_LCUHeight = LCUHeight; m_numberOfLevel = numberOfLevel; m_useLCUSeparateModel = useLCUSeparateModel; m_numberOfPixel = m_picWidth * m_picHeight; m_targetBits = (Int64)m_totalFrames * (Int64)m_targetRate / (Int64)m_frameRate; m_seqTargetBpp = (Double)m_targetRate / (Double)m_frameRate / (Double)m_numberOfPixel; if ( m_seqTargetBpp < 0.03 ) { m_alphaUpdate = 0.01; m_betaUpdate = 0.005; } else if ( m_seqTargetBpp < 0.08 ) { m_alphaUpdate = 0.05; m_betaUpdate = 0.025; } else if ( m_seqTargetBpp < 0.2 ) { m_alphaUpdate = 0.1; m_betaUpdate = 0.05; } else if ( m_seqTargetBpp < 0.5 ) { m_alphaUpdate = 0.2; m_betaUpdate = 0.1; } else { m_alphaUpdate = 0.4; m_betaUpdate = 0.2; } m_averageBits = (Int)(m_targetBits / totalFrames); Int picWidthInBU = ( m_picWidth % m_LCUWidth ) == 0 ? m_picWidth / m_LCUWidth : m_picWidth / m_LCUWidth + 1; Int picHeightInBU = ( m_picHeight % m_LCUHeight ) == 0 ? m_picHeight / m_LCUHeight : m_picHeight / m_LCUHeight + 1; m_numberOfLCU = picWidthInBU * picHeightInBU; m_bitsRatio = new Int[m_GOPSize]; for ( Int i=0; i0) { m_picPara[i].m_alpha = 3.2003; m_picPara[i].m_beta = -1.367; } else { m_picPara[i].m_alpha = ALPHA; m_picPara[i].m_beta = BETA2; } } } else { for ( Int i=0; igetAdaptiveBits() > 0 && encRCSeq->getLastLambda() > 0.1 ) #endif { Double targetBpp = (Double)targetBits / encRCSeq->getNumPixel(); Double basicLambda = 0.0; Double* lambdaRatio = new Double[encRCSeq->getGOPSize()]; Double* equaCoeffA = new Double[encRCSeq->getGOPSize()]; Double* equaCoeffB = new Double[encRCSeq->getGOPSize()]; if ( encRCSeq->getAdaptiveBits() == 1 ) // for GOP size =4, low delay case { if ( encRCSeq->getLastLambda() < 120.0 ) { lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.5793; lambdaRatio[0] = 1.3 * lambdaRatio[1]; lambdaRatio[2] = 1.3 * lambdaRatio[1]; lambdaRatio[3] = 1.0; } else { lambdaRatio[0] = 5.0; lambdaRatio[1] = 4.0; lambdaRatio[2] = 5.0; lambdaRatio[3] = 1.0; } } else if ( encRCSeq->getAdaptiveBits() == 2 ) // for GOP size = 8, random access case { if ( encRCSeq->getLastLambda() < 90.0 ) { lambdaRatio[0] = 1.0; lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.7963; lambdaRatio[2] = 1.3 * lambdaRatio[1]; lambdaRatio[3] = 3.25 * lambdaRatio[1]; lambdaRatio[4] = 3.25 * lambdaRatio[1]; lambdaRatio[5] = 1.3 * lambdaRatio[1]; lambdaRatio[6] = 3.25 * lambdaRatio[1]; lambdaRatio[7] = 3.25 * lambdaRatio[1]; } else { lambdaRatio[0] = 1.0; lambdaRatio[1] = 4.0; lambdaRatio[2] = 5.0; lambdaRatio[3] = 12.3; lambdaRatio[4] = 12.3; lambdaRatio[5] = 5.0; lambdaRatio[6] = 12.3; lambdaRatio[7] = 12.3; } } #if JVET_K0390_RATE_CTRL else if (encRCSeq->getAdaptiveBits() == 3) // for GOP size = 16, random access case { Double hierarQp = 4.2005 * log(encRCSeq->getLastLambda()) + 13.7122; // the qp of POC16 Double qpLev2 = (hierarQp + 0.0) + 0.2016 * (hierarQp + 0.0) - 4.8848; Double qpLev3 = (hierarQp + 3.0) + 0.22286 * (hierarQp + 3.0) - 5.7476; Double qpLev4 = (hierarQp + 4.0) + 0.2333 * (hierarQp + 4.0) - 5.9; Double qpLev5 = (hierarQp + 5.0) + 0.3 * (hierarQp + 5.0) - 7.1444; Double lambdaLev1 = exp((hierarQp - 13.7122) / 4.2005); Double lambdaLev2 = exp((qpLev2 - 13.7122) / 4.2005); Double lambdaLev3 = exp((qpLev3 - 13.7122) / 4.2005); Double lambdaLev4 = exp((qpLev4 - 13.7122) / 4.2005); Double lambdaLev5 = exp((qpLev5 - 13.7122) / 4.2005); lambdaRatio[0] = 1.0; lambdaRatio[1] = lambdaLev2 / lambdaLev1; lambdaRatio[2] = lambdaLev3 / lambdaLev1; lambdaRatio[3] = lambdaLev4 / lambdaLev1; lambdaRatio[4] = lambdaLev5 / lambdaLev1; lambdaRatio[5] = lambdaLev5 / lambdaLev1; lambdaRatio[6] = lambdaLev4 / lambdaLev1; lambdaRatio[7] = lambdaLev5 / lambdaLev1; lambdaRatio[8] = lambdaLev5 / lambdaLev1; lambdaRatio[9] = lambdaLev3 / lambdaLev1; lambdaRatio[10] = lambdaLev4 / lambdaLev1; lambdaRatio[11] = lambdaLev5 / lambdaLev1; lambdaRatio[12] = lambdaLev5 / lambdaLev1; lambdaRatio[13] = lambdaLev4 / lambdaLev1; lambdaRatio[14] = lambdaLev5 / lambdaLev1; lambdaRatio[15] = lambdaLev5 / lambdaLev1; #if JVET_M0600_RATE_CTRL const Double qdfParaLev2A = 0.5847; const Double qdfParaLev2B = -0.0782; const Double qdfParaLev3A = 0.5468; const Double qdfParaLev3B = -0.1364; const Double qdfParaLev4A = 0.6539; const Double qdfParaLev4B = -0.203; const Double qdfParaLev5A = 0.8623; const Double qdfParaLev5B = -0.4676; Double qdfLev1Lev2 = Clip3(0.12, 0.9, qdfParaLev2A * encRCSeq->getPicPara(2).m_skipRatio + qdfParaLev2B); Double qdfLev1Lev3 = Clip3(0.13, 0.9, qdfParaLev3A * encRCSeq->getPicPara(3).m_skipRatio + qdfParaLev3B); Double qdfLev1Lev4 = Clip3(0.15, 0.9, qdfParaLev4A * encRCSeq->getPicPara(4).m_skipRatio + qdfParaLev4B); Double qdfLev1Lev5 = Clip3(0.20, 0.9, qdfParaLev5A * encRCSeq->getPicPara(5).m_skipRatio + qdfParaLev5B); Double qdfLev2Lev3 = Clip3(0.09, 0.9, qdfLev1Lev3 * (1 - qdfLev1Lev2)); Double qdfLev2Lev4 = Clip3(0.12, 0.9, qdfLev1Lev4 * (1 - qdfLev1Lev2)); Double qdfLev2Lev5 = Clip3(0.14, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev2)); Double qdfLev3Lev4 = Clip3(0.06, 0.9, qdfLev1Lev4 * (1 - qdfLev1Lev3)); Double qdfLev3Lev5 = Clip3(0.09, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev3)); Double qdfLev4Lev5 = Clip3(0.10, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev4)); lambdaLev1 = 1 / (1 + 2 * (qdfLev1Lev2 + 2 * qdfLev1Lev3 + 4 * qdfLev1Lev4 + 8 * qdfLev1Lev5)); lambdaLev2 = 1 / (1 + (3 * qdfLev2Lev3 + 5 * qdfLev2Lev4 + 8 * qdfLev2Lev5)); lambdaLev3 = 1 / (1 + 2 * qdfLev3Lev4 + 4 * qdfLev3Lev5); lambdaLev4 = 1 / (1 + 2 * qdfLev4Lev5); lambdaLev5 = 1 / (1.0); lambdaRatio[0] = 1.0; lambdaRatio[1] = lambdaLev2 / lambdaLev1; lambdaRatio[2] = lambdaLev3 / lambdaLev1; lambdaRatio[3] = lambdaLev4 / lambdaLev1; lambdaRatio[4] = lambdaLev5 / lambdaLev1; lambdaRatio[5] = lambdaLev5 / lambdaLev1; lambdaRatio[6] = lambdaLev4 / lambdaLev1; lambdaRatio[7] = lambdaLev5 / lambdaLev1; lambdaRatio[8] = lambdaLev5 / lambdaLev1; lambdaRatio[9] = lambdaLev3 / lambdaLev1; lambdaRatio[10] = lambdaLev4 / lambdaLev1; lambdaRatio[11] = lambdaLev5 / lambdaLev1; lambdaRatio[12] = lambdaLev5 / lambdaLev1; lambdaRatio[13] = lambdaLev4 / lambdaLev1; lambdaRatio[14] = lambdaLev5 / lambdaLev1; lambdaRatio[15] = lambdaLev5 / lambdaLev1; #endif } #endif xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() ); #if JVET_K0390_RATE_CTRL basicLambda = xSolveEqua(encRCSeq, targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize()); #else basicLambda = xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() ); #endif encRCSeq->setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB ); delete []lambdaRatio; delete []equaCoeffA; delete []equaCoeffB; } m_picTargetBitInGOP = new Int[numPic]; Int i; Int totalPicRatio = 0; Int currPicRatio = 0; for ( i=0; igetBitRatio( i ); } for ( i=0; igetBitRatio( i ); m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio ); } m_encRCSeq = encRCSeq; m_numPic = numPic; m_targetBits = targetBits; m_picLeft = m_numPic; m_bitsLeft = m_targetBits; } Void TEncRCGOP::xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize ) { for ( Int i=0; igetGOPID2Level(i); Double alpha = encRCSeq->getPicPara(frameLevel).m_alpha; Double beta = encRCSeq->getPicPara(frameLevel).m_beta; equaCoeffA[i] = pow( 1.0/alpha, 1.0/beta ) * pow( lambdaRatio[i], 1.0/beta ); equaCoeffB[i] = 1.0/beta; } } #if JVET_K0390_RATE_CTRL Double TEncRCGOP::xSolveEqua(TEncRCSeq* encRCSeq, Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize) #else Double TEncRCGOP::xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize ) #endif { Double solution = 100.0; Double minNumber = 0.1; Double maxNumber = 10000.0; for ( Int i=0; igetPicPara(encRCSeq->getGOPID2Level(j)).m_validPix / (Double)encRCSeq->getNumPixel(); fx += actualBpp; #else fx += equaCoeffA[j] * pow( solution, equaCoeffB[j] ); #endif } if ( fabs( fx - targetBpp ) < 0.000001 ) { break; } if ( fx > targetBpp ) { minNumber = solution; solution = ( solution + maxNumber ) / 2.0; } else { maxNumber = solution; solution = ( solution + minNumber ) / 2.0; } } solution = Clip3( 0.1, 10000.0, solution ); return solution; } Void TEncRCGOP::destroy() { m_encRCSeq = NULL; if ( m_picTargetBitInGOP != NULL ) { delete[] m_picTargetBitInGOP; m_picTargetBitInGOP = NULL; } } Void TEncRCGOP::updateAfterPicture( Int bitsCost ) { m_bitsLeft -= bitsCost; m_picLeft--; } Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize ) { #if JVET_Y0105_SW_AND_QDF Int realInfluencePicture = min( g_RCSmoothWindowSizeAlpha * GOPSize / max(encRCSeq->getIntraPeriod(), 32) + g_RCSmoothWindowSizeBeta, encRCSeq->getFramesLeft() ); #else Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() ); #endif Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() ); Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture ); Int targetBits = currentTargetBitsPerPic * GOPSize; if ( targetBits < 200 ) { targetBits = 200; // at least allocate 200 bits for one GOP } return targetBits; } //picture level TEncRCPic::TEncRCPic() { m_encRCSeq = NULL; m_encRCGOP = NULL; m_frameLevel = 0; m_numberOfPixel = 0; m_numberOfLCU = 0; m_targetBits = 0; m_estHeaderBits = 0; m_estPicQP = 0; m_estPicLambda = 0.0; m_LCULeft = 0; m_bitsLeft = 0; m_pixelsLeft = 0; m_LCUs = NULL; m_picActualHeaderBits = 0; m_picActualBits = 0; m_picQP = 0; m_picLambda = 0.0; #if JVET_K0390_RATE_CTRL m_picMSE = 0.0; m_validPixelsInPic = 0; #endif } TEncRCPic::~TEncRCPic() { destroy(); } Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP ) { Int targetBits = 0; Int GOPbitsLeft = encRCGOP->getBitsLeft(); Int i; Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft(); Int currPicRatio = encRCSeq->getBitRatio( currPicPosition ); Int totalPicRatio = 0; for ( i=currPicPosition; igetNumPic(); i++ ) { totalPicRatio += encRCSeq->getBitRatio( i ); } targetBits = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio ); if ( targetBits < 100 ) { targetBits = 100; // at least allocate 100 bits for one picture } if ( m_encRCSeq->getFramesLeft() > 16 ) { targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) ); } return targetBits; } Int TEncRCPic::xEstPicHeaderBits( list& listPreviousPictures, Int frameLevel ) { Int numPreviousPics = 0; Int totalPreviousBits = 0; list::iterator it; for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) { if ( (*it)->getFrameLevel() == frameLevel ) { totalPreviousBits += (*it)->getPicActualHeaderBits(); numPreviousPics++; } } Int estHeaderBits = 0; if ( numPreviousPics > 0 ) { estHeaderBits = totalPreviousBits / numPreviousPics; } return estHeaderBits; } Int TEncRCPic::xEstPicLowerBound(TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP) { Int lowerBound = 0; Int GOPbitsLeft = encRCGOP->getBitsLeft(); const Int nextPicPosition = (encRCGOP->getNumPic() - encRCGOP->getPicLeft() + 1) % encRCGOP->getNumPic(); const Int nextPicRatio = encRCSeq->getBitRatio(nextPicPosition); Int totalPicRatio = 0; for (Int i = nextPicPosition; i < encRCGOP->getNumPic(); i++) { totalPicRatio += encRCSeq->getBitRatio(i); } if (nextPicPosition == 0) { GOPbitsLeft = encRCGOP->getTargetBits(); } else { GOPbitsLeft -= m_targetBits; } lowerBound = Int(((Double)GOPbitsLeft) * nextPicRatio / totalPicRatio); if (lowerBound < 100) { lowerBound = 100; // at least allocate 100 bits for one picture } if (m_encRCSeq->getFramesLeft() > 16) { lowerBound = Int(g_RCWeightPicRargetBitInBuffer * lowerBound + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP(nextPicPosition)); } return lowerBound; } Void TEncRCPic::addToPictureLsit( list& listPreviousPictures ) { if ( listPreviousPictures.size() > g_RCMaxPicListSize ) { TEncRCPic* p = listPreviousPictures.front(); listPreviousPictures.pop_front(); p->destroy(); delete p; } listPreviousPictures.push_back( this ); } Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list& listPreviousPictures ) { destroy(); m_encRCSeq = encRCSeq; m_encRCGOP = encRCGOP; Int targetBits = xEstPicTargetBits( encRCSeq, encRCGOP ); Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel ); if ( targetBits < estHeaderBits + 100 ) { targetBits = estHeaderBits + 100; // at least allocate 100 bits for picture data } m_frameLevel = frameLevel; m_numberOfPixel = encRCSeq->getNumPixel(); m_numberOfLCU = encRCSeq->getNumberOfLCU(); m_estPicLambda = 100.0; m_targetBits = targetBits; m_estHeaderBits = estHeaderBits; m_bitsLeft = m_targetBits; Int picWidth = encRCSeq->getPicWidth(); Int picHeight = encRCSeq->getPicHeight(); Int LCUWidth = encRCSeq->getLCUWidth(); Int LCUHeight = encRCSeq->getLCUHeight(); Int picWidthInLCU = ( picWidth % LCUWidth ) == 0 ? picWidth / LCUWidth : picWidth / LCUWidth + 1; Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1; m_lowerBound = xEstPicLowerBound( encRCSeq, encRCGOP ); m_LCULeft = m_numberOfLCU; m_bitsLeft -= m_estHeaderBits; m_pixelsLeft = m_numberOfPixel; m_LCUs = new TRCLCU[m_numberOfLCU]; Int i, j; Int LCUIdx; for ( i=0; i& listPreviousPictures, SliceType eSliceType) { Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; Double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta; Double bpp = (Double)m_targetBits/(Double)m_numberOfPixel; #if JVET_K0390_RATE_CTRL Int lastPicValPix = 0; if (listPreviousPictures.size() > 0) { lastPicValPix = m_encRCSeq->getPicPara(m_frameLevel).m_validPix; } if (lastPicValPix > 0) { bpp = (Double)m_targetBits / (Double)lastPicValPix; } #endif Double estLambda; if (eSliceType == I_SLICE) { estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp); } else { estLambda = alpha * pow( bpp, beta ); } Double lastLevelLambda = -1.0; Double lastPicLambda = -1.0; Double lastValidLambda = -1.0; list::iterator it; for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) { if ( (*it)->getFrameLevel() == m_frameLevel ) { lastLevelLambda = (*it)->getPicActualLambda(); } lastPicLambda = (*it)->getPicActualLambda(); if ( lastPicLambda > 0.0 ) { lastValidLambda = lastPicLambda; } } if ( lastLevelLambda > 0.0 ) { lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda ); estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda ); } if ( lastPicLambda > 0.0 ) { lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda ); estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda ); } else if ( lastValidLambda > 0.0 ) { lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda ); estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda ); } else { estLambda = Clip3( 0.1, 10000.0, estLambda ); } if ( estLambda < 0.1 ) { estLambda = 0.1; } #if JVET_K0390_RATE_CTRL //Avoid different results in different platforms. The problem is caused by the different results of pow() in different platforms. estLambda = Double(int64_t(estLambda * (Double)LAMBDA_PREC + 0.5)) / (Double)LAMBDA_PREC; #endif m_estPicLambda = estLambda; Double totalWeight = 0.0; // initial BU bit allocation weight for ( Int i=0; igetUseLCUSeparateModel() ) { alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha; betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta; } else { alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; betaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_beta; } m_LCUs[i].m_bitWeight = m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU ); if ( m_LCUs[i].m_bitWeight < 0.01 ) { m_LCUs[i].m_bitWeight = 0.01; } totalWeight += m_LCUs[i].m_bitWeight; } for ( Int i=0; i& listPreviousPictures ) { Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 ); Int lastLevelQP = g_RCInvalidQPValue; Int lastPicQP = g_RCInvalidQPValue; Int lastValidQP = g_RCInvalidQPValue; list::iterator it; for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) { if ( (*it)->getFrameLevel() == m_frameLevel ) { lastLevelQP = (*it)->getPicActualQP(); } lastPicQP = (*it)->getPicActualQP(); if ( lastPicQP > g_RCInvalidQPValue ) { lastValidQP = lastPicQP; } } if ( lastLevelQP > g_RCInvalidQPValue ) { QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP ); } if( lastPicQP > g_RCInvalidQPValue ) { QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP ); } else if( lastValidQP > g_RCInvalidQPValue ) { QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP ); } return QP; } Double TEncRCPic::getLCUTargetBpp(SliceType eSliceType) { Int LCUIdx = getLCUCoded(); Double bpp = -1.0; Int avgBits = 0; if (eSliceType == I_SLICE) { Int noOfLCUsLeft = m_numberOfLCU - LCUIdx + 1; Int bitrateWindow = min(4,noOfLCUsLeft); Double MAD = getLCU(LCUIdx).m_costIntra; if (m_remainingCostIntra > 0.1 ) { Double weightedBitsLeft = (m_bitsLeft*bitrateWindow+(m_bitsLeft-getLCU(LCUIdx).m_targetBitsLeft)*noOfLCUsLeft)/(Double)bitrateWindow; avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra ); } else { avgBits = Int( m_bitsLeft / m_LCULeft ); } m_remainingCostIntra -= MAD; } else { Double totalWeight = 0; for ( Int i=LCUIdx; igetUseLCUSeparateModel() ) { alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha; beta = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta; } else { alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta; } Double estLambda = alpha * pow( bpp, beta ); //for Lambda clip, picture level clip Double clipPicLambda = m_estPicLambda; //for Lambda clip, LCU level clip Double clipNeighbourLambda = -1.0; for ( Int i=LCUIdx - 1; i>=0; i-- ) { if ( m_LCUs[i].m_lambda > 0 ) { clipNeighbourLambda = m_LCUs[i].m_lambda; break; } } if ( clipNeighbourLambda > 0.0 ) { estLambda = Clip3( clipNeighbourLambda * pow( 2.0, -1.0/3.0 ), clipNeighbourLambda * pow( 2.0, 1.0/3.0 ), estLambda ); } if ( clipPicLambda > 0.0 ) { estLambda = Clip3( clipPicLambda * pow( 2.0, -2.0/3.0 ), clipPicLambda * pow( 2.0, 2.0/3.0 ), estLambda ); } else { estLambda = Clip3( 10.0, 1000.0, estLambda ); } if ( estLambda < 0.1 ) { estLambda = 0.1; } #if JVET_K0390_RATE_CTRL //Avoid different results in different platforms. The problem is caused by the different results of pow() in different platforms. estLambda = Double(int64_t(estLambda * (Double)LAMBDA_PREC + 0.5)) / (Double)LAMBDA_PREC; #endif return estLambda; } Int TEncRCPic::getLCUEstQP( Double lambda, Int clipPicQP ) { Int LCUIdx = getLCUCoded(); Int estQP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 ); //for Lambda clip, LCU level clip Int clipNeighbourQP = g_RCInvalidQPValue; for ( Int i=LCUIdx - 1; i>=0; i-- ) { if ( (getLCU(i)).m_QP > g_RCInvalidQPValue ) { clipNeighbourQP = getLCU(i).m_QP; break; } } if ( clipNeighbourQP > g_RCInvalidQPValue ) { estQP = Clip3( clipNeighbourQP - 1, clipNeighbourQP + 1, estQP ); } estQP = Clip3( clipPicQP - 2, clipPicQP + 2, estQP ); return estQP; } #if JVET_M0600_RATE_CTRL Void TEncRCPic::updateAfterCTU(Int LCUIdx, Int bits, Int QP, Double lambda, Double skipRatio, Bool updateLCUParameter) #else Void TEncRCPic::updateAfterCTU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter ) #endif { m_LCUs[LCUIdx].m_actualBits = bits; m_LCUs[LCUIdx].m_QP = QP; m_LCUs[LCUIdx].m_lambda = lambda; #if JVET_K0390_RATE_CTRL m_LCUs[LCUIdx].m_actualSSE = m_LCUs[LCUIdx].m_actualMSE * m_LCUs[LCUIdx].m_numberOfPixel; #endif m_LCULeft--; m_bitsLeft -= bits; m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel; if ( !updateLCUParameter ) { return; } if ( !m_encRCSeq->getUseLCUSeparateModel() ) { return; } Double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha; Double beta = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta; Int LCUActualBits = m_LCUs[LCUIdx].m_actualBits; Int LCUTotalPixels = m_LCUs[LCUIdx].m_numberOfPixel; Double bpp = ( Double )LCUActualBits/( Double )LCUTotalPixels; Double calLambda = alpha * pow( bpp, beta ); Double inputLambda = m_LCUs[LCUIdx].m_lambda; if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 ) { alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 ); beta *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 ); alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha ); beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta ); TRCParameter rcPara; rcPara.m_alpha = alpha; rcPara.m_beta = beta; #if JVET_M0600_RATE_CTRL rcPara.m_skipRatio = skipRatio; #endif #if JVET_K0390_RATE_CTRL if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1) { rcPara.m_validPix = 0; } else { rcPara.m_validPix = LCUTotalPixels; } Double MSE = m_LCUs[LCUIdx].m_actualMSE; Double updatedK = bpp * inputLambda / MSE; Double updatedC = MSE / pow(bpp, -updatedK); rcPara.m_alpha = updatedC * updatedK; rcPara.m_beta = -updatedK - 1.0; if (bpp > 0 && updatedK > 0.0001) { m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara); } else { rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha); m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara); } #else m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara ); #endif return; } calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda ); alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha; Double lnbpp = log( bpp ); lnbpp = Clip3( -5.0, -0.1, lnbpp ); beta += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp; alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha ); beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta ); TRCParameter rcPara; rcPara.m_alpha = alpha; rcPara.m_beta = beta; #if JVET_M0600_RATE_CTRL rcPara.m_skipRatio = skipRatio; #endif #if JVET_K0390_RATE_CTRL if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1) { rcPara.m_validPix = 0; } else { rcPara.m_validPix = LCUTotalPixels; } Double MSE = m_LCUs[LCUIdx].m_actualMSE; Double updatedK = bpp * inputLambda / MSE; Double updatedC = MSE / pow(bpp, -updatedK); rcPara.m_alpha = updatedC * updatedK; rcPara.m_beta = -updatedK - 1.0; if (bpp > 0 && updatedK > 0.0001) { m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara); } else { rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha); m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara); } #else m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara ); #endif } Double TEncRCPic::calAverageQP() { Int totalQPs = 0; Int numTotalLCUs = 0; Int i; for ( i=0; i 0 ) { totalQPs += m_LCUs[i].m_QP; numTotalLCUs++; } } Double avgQP = 0.0; if ( numTotalLCUs == 0 ) { avgQP = g_RCInvalidQPValue; } else { avgQP = ((Double)totalQPs) / ((Double)numTotalLCUs); } return avgQP; } Double TEncRCPic::calAverageLambda() { Double totalLambdas = 0.0; Int numTotalLCUs = 0; #if JVET_K0390_RATE_CTRL Double totalSSE = 0.0; Int totalPixels = 0; #endif Int i; for ( i=0; i 0.01 ) { #if JVET_K0390_RATE_CTRL if (m_LCUs[i].m_QP > 0 || m_encRCSeq->getAdaptiveBits() != 1) { m_validPixelsInPic += m_LCUs[i].m_numberOfPixel; totalLambdas += log(m_LCUs[i].m_lambda); numTotalLCUs++; } #else totalLambdas += log( m_LCUs[i].m_lambda ); numTotalLCUs++; #endif #if JVET_K0390_RATE_CTRL if (m_LCUs[i].m_QP > 0 || m_encRCSeq->getAdaptiveBits() != 1) { totalSSE += m_LCUs[i].m_actualSSE; totalPixels += m_LCUs[i].m_numberOfPixel; } #endif } } #if JVET_K0390_RATE_CTRL setPicMSE(totalPixels > 0 ? totalSSE / (Double)totalPixels : 1.0); //1.0 is useless in the following process, just to make sure the divisor not be 0 #endif Double avgLambda; if( numTotalLCUs == 0 ) { avgLambda = -1.0; } else { avgLambda = pow( 2.7183, totalLambdas / numTotalLCUs ); } return avgLambda; } Void TEncRCPic::updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType) { m_picActualHeaderBits = actualHeaderBits; m_picActualBits = actualTotalBits; if ( averageQP > 0.0 ) { m_picQP = Int( averageQP + 0.5 ); } else { m_picQP = g_RCInvalidQPValue; } m_picLambda = averageLambda; Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; Double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta; #if JVET_M0600_RATE_CTRL //calculate the skipRatio of picture Double skipRatio = 0; Int numOfSkipPixel = 0; for (Int LCUIdx = 0; LCUIdx < m_numberOfLCU; LCUIdx++) { numOfSkipPixel += Int(m_encRCSeq->getLCUPara(m_frameLevel, LCUIdx).m_skipRatio*m_LCUs[LCUIdx].m_numberOfPixel); } skipRatio = (Double)numOfSkipPixel / (Double)m_numberOfPixel; #endif if (eSliceType == I_SLICE) { updateAlphaBetaIntra(&alpha, &beta); } else { // update parameters Double picActualBits = ( Double )m_picActualBits; #if JVET_K0390_RATE_CTRL Double picActualBpp = picActualBits / (Double)m_validPixelsInPic; #else Double picActualBpp = picActualBits/(Double)m_numberOfPixel; #endif Double calLambda = alpha * pow( picActualBpp, beta ); Double inputLambda = m_picLambda; if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 ) { alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 ); beta *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 ); alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha ); beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta ); TRCParameter rcPara; rcPara.m_alpha = alpha; rcPara.m_beta = beta; #if JVET_M0600_RATE_CTRL rcPara.m_skipRatio = skipRatio; #endif #if JVET_K0390_RATE_CTRL Double avgMSE = getPicMSE(); Double updatedK = picActualBpp * averageLambda / avgMSE; Double updatedC = avgMSE / pow(picActualBpp, -updatedK); if (m_frameLevel > 0) //only use for level > 0 { rcPara.m_alpha = updatedC * updatedK; rcPara.m_beta = -updatedK - 1.0; } rcPara.m_validPix = m_validPixelsInPic; if (m_validPixelsInPic > 0) { m_encRCSeq->setPicPara(m_frameLevel, rcPara); } #else m_encRCSeq->setPicPara( m_frameLevel, rcPara ); #endif return; } calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda ); alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha; Double lnbpp = log( picActualBpp ); lnbpp = Clip3( -5.0, -0.1, lnbpp ); beta += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp; alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha ); beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta ); } TRCParameter rcPara; rcPara.m_alpha = alpha; rcPara.m_beta = beta; #if JVET_M0600_RATE_CTRL rcPara.m_skipRatio = skipRatio; #endif #if JVET_K0390_RATE_CTRL Double picActualBpp = (Double)m_picActualBits / (Double)m_validPixelsInPic; Double avgMSE = getPicMSE(); Double updatedK = picActualBpp * averageLambda / avgMSE; Double updatedC = avgMSE / pow(picActualBpp, -updatedK); if (m_frameLevel > 0) //only use for level > 0 { rcPara.m_alpha = updatedC * updatedK; rcPara.m_beta = -updatedK - 1.0; } rcPara.m_validPix = m_validPixelsInPic; if (m_validPixelsInPic > 0) { m_encRCSeq->setPicPara(m_frameLevel, rcPara); } #else m_encRCSeq->setPicPara( m_frameLevel, rcPara ); #endif if ( m_frameLevel == 1 ) { Double currLambda = Clip3( 0.1, 10000.0, m_picLambda ); Double updateLastLambda = g_RCWeightHistoryLambda * m_encRCSeq->getLastLambda() + g_RCWeightCurrentLambda * currLambda; m_encRCSeq->setLastLambda( updateLastLambda ); } } Int TEncRCPic::getRefineBitsForIntra( Int orgBits ) { Double alpha=0.25, beta=0.5582; Int iIntraBits; if (orgBits*40 < m_numberOfPixel) { alpha=0.25; } else { alpha=0.30; } iIntraBits = (Int)(alpha* pow(m_totalCostIntra*4.0/(Double)orgBits, beta)*(Double)orgBits+0.5); return iIntraBits; } Double TEncRCPic::calculateLambdaIntra(Double alpha, Double beta, Double MADPerPixel, Double bitsPerPixel) { return ( (alpha/256.0) * pow( MADPerPixel/bitsPerPixel, beta ) ); } Void TEncRCPic::updateAlphaBetaIntra(Double *alpha, Double *beta) { Double lnbpp = log(pow(m_totalCostIntra / (Double)m_numberOfPixel, BETA1)); Double diffLambda = (*beta)*(log((Double)m_picActualBits)-log((Double)m_targetBits)); diffLambda = Clip3(-0.125, 0.125, 0.25*diffLambda); *alpha = (*alpha) * exp(diffLambda); *beta = (*beta) + diffLambda / lnbpp; } Void TEncRCPic::getLCUInitTargetBits() { Int iAvgBits = 0; m_remainingCostIntra = m_totalCostIntra; for (Int i=m_numberOfLCU-1; i>=0; i--) { iAvgBits += Int(m_targetBits * getLCU(i).m_costIntra/m_totalCostIntra); getLCU(i).m_targetBitsLeft = iAvgBits; } } Double TEncRCPic::getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP) { Int LCUIdx = getLCUCoded(); Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; Double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta; Double costPerPixel = getLCU(LCUIdx).m_costIntra/(Double)getLCU(LCUIdx).m_numberOfPixel; costPerPixel = pow(costPerPixel, BETA1); Double estLambda = calculateLambdaIntra(alpha, beta, costPerPixel, bpp); Int clipNeighbourQP = g_RCInvalidQPValue; for (Int i=LCUIdx-1; i>=0; i--) { if ((getLCU(i)).m_QP > g_RCInvalidQPValue) { clipNeighbourQP = getLCU(i).m_QP; break; } } Int minQP = clipPicQP - 2; Int maxQP = clipPicQP + 2; if ( clipNeighbourQP > g_RCInvalidQPValue ) { maxQP = min(clipNeighbourQP + 1, maxQP); minQP = max(clipNeighbourQP - 1, minQP); } Double maxLambda=exp(((Double)(maxQP+0.49)-13.7122)/4.2005); Double minLambda=exp(((Double)(minQP-0.49)-13.7122)/4.2005); estLambda = Clip3(minLambda, maxLambda, estLambda); #if JVET_K0390_RATE_CTRL //Avoid different results in different platforms. The problem is caused by the different results of pow() in different platforms. estLambda = Double(int64_t(estLambda * (Double)LAMBDA_PREC + 0.5)) / (Double)LAMBDA_PREC; #endif *estQP = Int( 4.2005 * log(estLambda) + 13.7122 + 0.5 ); *estQP = Clip3(minQP, maxQP, *estQP); return estLambda; } TEncRateCtrl::TEncRateCtrl() { m_encRCSeq = NULL; m_encRCGOP = NULL; m_encRCPic = NULL; } TEncRateCtrl::~TEncRateCtrl() { destroy(); } Void TEncRateCtrl::destroy() { if ( m_encRCSeq != NULL ) { delete m_encRCSeq; m_encRCSeq = NULL; } if ( m_encRCGOP != NULL ) { delete m_encRCGOP; m_encRCGOP = NULL; } while ( m_listRCPictures.size() > 0 ) { TEncRCPic* p = m_listRCPictures.front(); m_listRCPictures.pop_front(); delete p; } } #if JVET_Y0105_SW_AND_QDF Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int intraPeriod, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] ) #else Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] ) #endif { destroy(); Bool isLowdelay = true; for ( Int i=0; i GOPList[i+1].m_POC ) { isLowdelay = false; break; } } Int numberOfLevel = 1; Int adaptiveBit = 0; if ( keepHierBits > 0 ) { numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1; } #if JVET_K0390_RATE_CTRL if (!isLowdelay && (GOPSize == 16 || GOPSize == 8)) #else if ( !isLowdelay && GOPSize == 8 ) #endif { numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1; } numberOfLevel++; // intra picture numberOfLevel++; // non-reference picture Int* bitsRatio; bitsRatio = new Int[ GOPSize ]; for ( Int i=0; i 0 ) { Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) ); if ( GOPSize == 4 && isLowdelay ) { if ( bpp > 0.2 ) { bitsRatio[0] = 2; bitsRatio[1] = 3; bitsRatio[2] = 2; bitsRatio[3] = 6; } else if( bpp > 0.1 ) { bitsRatio[0] = 2; bitsRatio[1] = 3; bitsRatio[2] = 2; bitsRatio[3] = 10; } else if ( bpp > 0.05 ) { bitsRatio[0] = 2; bitsRatio[1] = 3; bitsRatio[2] = 2; bitsRatio[3] = 12; } else { bitsRatio[0] = 2; bitsRatio[1] = 3; bitsRatio[2] = 2; bitsRatio[3] = 14; } if ( keepHierBits == 2 ) { adaptiveBit = 1; } } else if ( GOPSize == 8 && !isLowdelay ) { if ( bpp > 0.2 ) { bitsRatio[0] = 15; bitsRatio[1] = 5; bitsRatio[2] = 4; bitsRatio[3] = 1; bitsRatio[4] = 1; bitsRatio[5] = 4; bitsRatio[6] = 1; bitsRatio[7] = 1; } else if ( bpp > 0.1 ) { bitsRatio[0] = 20; bitsRatio[1] = 6; bitsRatio[2] = 4; bitsRatio[3] = 1; bitsRatio[4] = 1; bitsRatio[5] = 4; bitsRatio[6] = 1; bitsRatio[7] = 1; } else if ( bpp > 0.05 ) { bitsRatio[0] = 25; bitsRatio[1] = 7; bitsRatio[2] = 4; bitsRatio[3] = 1; bitsRatio[4] = 1; bitsRatio[5] = 4; bitsRatio[6] = 1; bitsRatio[7] = 1; } else { bitsRatio[0] = 30; bitsRatio[1] = 8; bitsRatio[2] = 4; bitsRatio[3] = 1; bitsRatio[4] = 1; bitsRatio[5] = 4; bitsRatio[6] = 1; bitsRatio[7] = 1; } if ( keepHierBits == 2 ) { adaptiveBit = 2; } } #if JVET_K0390_RATE_CTRL else if (GOPSize == 16 && !isLowdelay) { if (bpp > 0.2) { bitsRatio[0] = 10; bitsRatio[1] = 8; bitsRatio[2] = 4; bitsRatio[3] = 2; bitsRatio[4] = 1; bitsRatio[5] = 1; bitsRatio[6] = 2; bitsRatio[7] = 1; bitsRatio[8] = 1; bitsRatio[9] = 4; bitsRatio[10] = 2; bitsRatio[11] = 1; bitsRatio[12] = 1; bitsRatio[13] = 2; bitsRatio[14] = 1; bitsRatio[15] = 1; } else if (bpp > 0.1) { bitsRatio[0] = 15; bitsRatio[1] = 9; bitsRatio[2] = 4; bitsRatio[3] = 2; bitsRatio[4] = 1; bitsRatio[5] = 1; bitsRatio[6] = 2; bitsRatio[7] = 1; bitsRatio[8] = 1; bitsRatio[9] = 4; bitsRatio[10] = 2; bitsRatio[11] = 1; bitsRatio[12] = 1; bitsRatio[13] = 2; bitsRatio[14] = 1; bitsRatio[15] = 1; } else if (bpp > 0.05) { bitsRatio[0] = 40; bitsRatio[1] = 17; bitsRatio[2] = 7; bitsRatio[3] = 2; bitsRatio[4] = 1; bitsRatio[5] = 1; bitsRatio[6] = 2; bitsRatio[7] = 1; bitsRatio[8] = 1; bitsRatio[9] = 7; bitsRatio[10] = 2; bitsRatio[11] = 1; bitsRatio[12] = 1; bitsRatio[13] = 2; bitsRatio[14] = 1; bitsRatio[15] = 1; } else { bitsRatio[0] = 40; bitsRatio[1] = 15; bitsRatio[2] = 6; bitsRatio[3] = 3; bitsRatio[4] = 1; bitsRatio[5] = 1; bitsRatio[6] = 3; bitsRatio[7] = 1; bitsRatio[8] = 1; bitsRatio[9] = 6; bitsRatio[10] = 3; bitsRatio[11] = 1; bitsRatio[12] = 1; bitsRatio[13] = 3; bitsRatio[14] = 1; bitsRatio[15] = 1; } if (keepHierBits == 2) { adaptiveBit = 3; } } #endif else { printf( "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" ); } } Int* GOPID2Level = new Int[ GOPSize ]; for ( Int i=0; i 0 ) { if ( GOPSize == 4 && isLowdelay ) { GOPID2Level[0] = 3; GOPID2Level[1] = 2; GOPID2Level[2] = 3; GOPID2Level[3] = 1; } else if ( GOPSize == 8 && !isLowdelay ) { GOPID2Level[0] = 1; GOPID2Level[1] = 2; GOPID2Level[2] = 3; GOPID2Level[3] = 4; GOPID2Level[4] = 4; GOPID2Level[5] = 3; GOPID2Level[6] = 4; GOPID2Level[7] = 4; } #if JVET_K0390_RATE_CTRL else if (GOPSize == 16 && !isLowdelay) { GOPID2Level[0] = 1; GOPID2Level[1] = 2; GOPID2Level[2] = 3; GOPID2Level[3] = 4; GOPID2Level[4] = 5; GOPID2Level[5] = 5; GOPID2Level[6] = 4; GOPID2Level[7] = 5; GOPID2Level[8] = 5; GOPID2Level[9] = 3; GOPID2Level[10] = 4; GOPID2Level[11] = 5; GOPID2Level[12] = 5; GOPID2Level[13] = 4; GOPID2Level[14] = 5; GOPID2Level[15] = 5; } #endif } if ( !isLowdelay && GOPSize == 8 ) { GOPID2Level[0] = 1; GOPID2Level[1] = 2; GOPID2Level[2] = 3; GOPID2Level[3] = 4; GOPID2Level[4] = 4; GOPID2Level[5] = 3; GOPID2Level[6] = 4; GOPID2Level[7] = 4; } #if JVET_K0390_RATE_CTRL else if (GOPSize == 16 && !isLowdelay) { GOPID2Level[0] = 1; GOPID2Level[1] = 2; GOPID2Level[2] = 3; GOPID2Level[3] = 4; GOPID2Level[4] = 5; GOPID2Level[5] = 5; GOPID2Level[6] = 4; GOPID2Level[7] = 5; GOPID2Level[8] = 5; GOPID2Level[9] = 3; GOPID2Level[10] = 4; GOPID2Level[11] = 5; GOPID2Level[12] = 5; GOPID2Level[13] = 4; GOPID2Level[14] = 5; GOPID2Level[15] = 5; } #endif m_encRCSeq = new TEncRCSeq; #if JVET_Y0105_SW_AND_QDF m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, intraPeriod, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit ); #else m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit ); #endif m_encRCSeq->initBitsRatio( bitsRatio ); m_encRCSeq->initGOPID2Level( GOPID2Level ); m_encRCSeq->initPicPara(); if ( useLCUSeparateModel ) { m_encRCSeq->initLCUPara(); } m_CpbSaturationEnabled = false; m_cpbSize = targetBitrate; m_cpbState = (UInt)(m_cpbSize*0.5f); m_bufferingRate = (Int)(targetBitrate / frameRate); delete[] bitsRatio; delete[] GOPID2Level; } Void TEncRateCtrl::initRCPic( Int frameLevel ) { m_encRCPic = new TEncRCPic; m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures ); } Void TEncRateCtrl::initRCGOP( Int numberOfPictures ) { m_encRCGOP = new TEncRCGOP; #if JVET_Y0105_SW_AND_QDF bool useAdaptiveBitsRatio = ( m_encRCSeq->getAdaptiveBits() > 0 ) && ( m_listRCPictures.size() >= m_encRCSeq->getGOPSize() ); m_encRCGOP->create( m_encRCSeq, numberOfPictures, useAdaptiveBitsRatio); #else m_encRCGOP->create( m_encRCSeq, numberOfPictures ); #endif } Int TEncRateCtrl::updateCpbState(Int actualBits) { Int cpbState = 1; m_cpbState -= actualBits; if (m_cpbState < 0) { cpbState = -1; } m_cpbState += m_bufferingRate; if (m_cpbState > m_cpbSize) { cpbState = 0; } return cpbState; } Void TEncRateCtrl::initHrdParam(const TComHRD* pcHrd, Int iFrameRate, Double fInitialCpbFullness) { m_CpbSaturationEnabled = true; m_cpbSize = (pcHrd->getCpbSizeValueMinus1(0, 0, 0) + 1) << (4 + pcHrd->getCpbSizeScale()); m_cpbState = (UInt)(m_cpbSize*fInitialCpbFullness); m_bufferingRate = (UInt)(((pcHrd->getBitRateValueMinus1(0, 0, 0) + 1) << (6 + pcHrd->getBitRateScale())) / iFrameRate); printf("\nHRD - [Initial CPB state %6d] [CPB Size %6d] [Buffering Rate %6d]\n", m_cpbState, m_cpbSize, m_bufferingRate); } Void TEncRateCtrl::destroyRCGOP() { delete m_encRCGOP; m_encRCGOP = NULL; } HM-HM-18.0/source/Lib/TLibEncoder/TEncRateCtrl.h000066400000000000000000000367231442026013100210570ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncRateCtrl.h \brief Rate control manager class */ #ifndef __TENCRATECTRL__ #define __TENCRATECTRL__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "../TLibCommon/CommonDef.h" #include "../TLibCommon/TComDataCU.h" #include #include using namespace std; //! \ingroup TLibEncoder //! \{ #include "../TLibEncoder/TEncCfg.h" #include #include const Int g_RCInvalidQPValue = -999; #if JVET_Y0105_SW_AND_QDF const int g_RCSmoothWindowSizeAlpha = 20; const int g_RCSmoothWindowSizeBeta = 60; #else const int g_RCSmoothWindowSize = 40; #endif const Int g_RCMaxPicListSize = 32; const Double g_RCWeightPicTargetBitInGOP = 0.9; const Double g_RCWeightPicRargetBitInBuffer = 1.0 - g_RCWeightPicTargetBitInGOP; const Int g_RCIterationNum = 20; const Double g_RCWeightHistoryLambda = 0.5; const Double g_RCWeightCurrentLambda = 1.0 - g_RCWeightHistoryLambda; const Int g_RCLCUSmoothWindowSize = 4; const Double g_RCAlphaMinValue = 0.05; const Double g_RCAlphaMaxValue = 500.0; const Double g_RCBetaMinValue = -3.0; const Double g_RCBetaMaxValue = -0.1; #if JVET_K0390_RATE_CTRL const Int LAMBDA_PREC = 1000000; #endif #define ALPHA 6.7542; #define BETA1 1.2517 #define BETA2 1.7860 struct TRCLCU { Int m_actualBits; Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue Int m_targetBits; Double m_lambda; Double m_bitWeight; Int m_numberOfPixel; Double m_costIntra; Int m_targetBitsLeft; #if JVET_K0390_RATE_CTRL Double m_actualSSE; Double m_actualMSE; #endif }; struct TRCParameter { Double m_alpha; Double m_beta; #if JVET_K0390_RATE_CTRL Int m_validPix; #endif #if JVET_M0600_RATE_CTRL Double m_skipRatio; #endif }; class TEncRCSeq { public: TEncRCSeq(); ~TEncRCSeq(); public: #if JVET_Y0105_SW_AND_QDF Void create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int intraPeriod, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ); #else Void create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ); #endif Void destroy(); Void initBitsRatio( Int bitsRatio[] ); Void initGOPID2Level( Int GOPID2Level[] ); Void initPicPara( TRCParameter* picPara = NULL ); // NULL to initial with default value Void initLCUPara( TRCParameter** LCUPara = NULL ); // NULL to initial with default value Void updateAfterPic ( Int bits ); Void setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB ); public: Int getTotalFrames() { return m_totalFrames; } Int getTargetRate() { return m_targetRate; } Int getFrameRate() { return m_frameRate; } Int getGOPSize() { return m_GOPSize; } #if JVET_Y0105_SW_AND_QDF Int getIntraPeriod() { return m_intraPeriod; } #endif Int getPicWidth() { return m_picWidth; } Int getPicHeight() { return m_picHeight; } Int getLCUWidth() { return m_LCUWidth; } Int getLCUHeight() { return m_LCUHeight; } Int getNumberOfLevel() { return m_numberOfLevel; } Int getAverageBits() { return m_averageBits; } Int getLeftAverageBits() { assert( m_framesLeft > 0 ); return (Int)(m_bitsLeft / m_framesLeft); } Bool getUseLCUSeparateModel() { return m_useLCUSeparateModel; } Int getNumPixel() { return m_numberOfPixel; } Int64 getTargetBits() { return m_targetBits; } Int getNumberOfLCU() { return m_numberOfLCU; } Int* getBitRatio() { return m_bitsRatio; } Int getBitRatio( Int idx ) { assert( idx& listPreviousPictures ); Void destroy(); Int estimatePicQP ( Double lambda, list& listPreviousPictures ); Int getRefineBitsForIntra(Int orgBits); Double calculateLambdaIntra(Double alpha, Double beta, Double MADPerPixel, Double bitsPerPixel); Double estimatePicLambda( list& listPreviousPictures, SliceType eSliceType); Void updateAlphaBetaIntra(Double *alpha, Double *beta); Double getLCUTargetBpp(SliceType eSliceType); Double getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP); Double getLCUEstLambda( Double bpp ); Int getLCUEstQP( Double lambda, Int clipPicQP ); #if JVET_M0600_RATE_CTRL void updateAfterCTU( Int LCUIdx, Int bits, Int QP, Double lambda, Double skipRatio, Bool updateLCUParameter = true); #else Void updateAfterCTU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter = true ); #endif Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType); Void addToPictureLsit( list& listPreviousPictures ); Double calAverageQP(); Double calAverageLambda(); private: Int xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP ); Int xEstPicHeaderBits( list& listPreviousPictures, Int frameLevel ); Int xEstPicLowerBound( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP ); public: TEncRCSeq* getRCSequence() { return m_encRCSeq; } TEncRCGOP* getRCGOP() { return m_encRCGOP; } Int getFrameLevel() { return m_frameLevel; } Int getNumberOfPixel() { return m_numberOfPixel; } Int getNumberOfLCU() { return m_numberOfLCU; } Int getTargetBits() { return m_targetBits; } Int getEstHeaderBits() { return m_estHeaderBits; } Int getLCULeft() { return m_LCULeft; } Int getBitsLeft() { return m_bitsLeft; } Int getPixelsLeft() { return m_pixelsLeft; } Int getBitsCoded() { return m_targetBits - m_estHeaderBits - m_bitsLeft; } Int getLCUCoded() { return m_numberOfLCU - m_LCULeft; } Int getLowerBound() { return m_lowerBound; } TRCLCU* getLCU() { return m_LCUs; } TRCLCU& getLCU( Int LCUIdx ) { return m_LCUs[LCUIdx]; } Int getPicActualHeaderBits() { return m_picActualHeaderBits; } Void setBitLeft(Int bits) { m_bitsLeft = bits; } Void setTargetBits( Int bits ) { m_targetBits = bits; m_bitsLeft = bits;} Void setTotalIntraCost(Double cost) { m_totalCostIntra = cost; } Void getLCUInitTargetBits(); Int getPicActualBits() { return m_picActualBits; } Int getPicActualQP() { return m_picQP; } Double getPicActualLambda() { return m_picLambda; } Int getPicEstQP() { return m_estPicQP; } Void setPicEstQP( Int QP ) { m_estPicQP = QP; } Double getPicEstLambda() { return m_estPicLambda; } Void setPicEstLambda( Double lambda ) { m_picLambda = lambda; } #if JVET_K0390_RATE_CTRL Double getPicMSE() { return m_picMSE; } void setPicMSE(Double avgMSE) { m_picMSE = avgMSE; } #endif private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; Int m_frameLevel; Int m_numberOfPixel; Int m_numberOfLCU; Int m_targetBits; Int m_estHeaderBits; Int m_estPicQP; Int m_lowerBound; Double m_estPicLambda; Int m_LCULeft; Int m_bitsLeft; Int m_pixelsLeft; TRCLCU* m_LCUs; Int m_picActualHeaderBits; // only SH and potential APS Double m_totalCostIntra; Double m_remainingCostIntra; Int m_picActualBits; // the whole picture, including header Int m_picQP; // in integer form Double m_picLambda; #if JVET_K0390_RATE_CTRL Double m_picMSE; Int m_validPixelsInPic; #endif }; class TEncRateCtrl { public: TEncRateCtrl(); ~TEncRateCtrl(); public: #if JVET_Y0105_SW_AND_QDF Void init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int intraPeriod, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] ); #else Void init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] ); #endif Void destroy(); Void initRCPic( Int frameLevel ); Void initRCGOP( Int numberOfPictures ); Void destroyRCGOP(); public: Void setRCQP ( Int QP ) { m_RCQP = QP; } Int getRCQP () { return m_RCQP; } TEncRCSeq* getRCSeq() { assert ( m_encRCSeq != NULL ); return m_encRCSeq; } TEncRCGOP* getRCGOP() { assert ( m_encRCGOP != NULL ); return m_encRCGOP; } TEncRCPic* getRCPic() { assert ( m_encRCPic != NULL ); return m_encRCPic; } list& getPicList() { return m_listRCPictures; } Bool getCpbSaturationEnabled() { return m_CpbSaturationEnabled; } UInt getCpbState() { return m_cpbState; } UInt getCpbSize() { return m_cpbSize; } UInt getBufferingRate() { return m_bufferingRate; } Int updateCpbState(Int actualBits); Void initHrdParam(const TComHRD* pcHrd, Int iFrameRate, Double fInitialCpbFullness); private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; TEncRCPic* m_encRCPic; list m_listRCPictures; Int m_RCQP; Bool m_CpbSaturationEnabled; // Enable target bits saturation to avoid CPB overflow and underflow Int m_cpbState; // CPB State UInt m_cpbSize; // CPB size UInt m_bufferingRate; // Buffering rate }; #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.cpp000066400000000000000000001305121442026013100237270ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSampleAdaptiveOffset.cpp \brief estimation part of sample adaptive offset class */ #include "TEncSampleAdaptiveOffset.h" #include #include #include #include //! \ingroup TLibEncoder //! \{ //! rounding with IBDI inline Double xRoundIbdi2(Int bitDepth, Double x) { return ((x)>0) ? (Int)(((Int)(x)+(1<<(bitDepth-8-1)))/(1<<(bitDepth-8))) : ((Int)(((Int)(x)-(1<<(bitDepth-8-1)))/(1<<(bitDepth-8)))); } inline Double xRoundIbdi(Int bitDepth, Double x) { return (bitDepth > 8 ? xRoundIbdi2(bitDepth, (x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ; } TEncSampleAdaptiveOffset::TEncSampleAdaptiveOffset() { m_pppcRDSbacCoder = NULL; m_pcRDGoOnSbacCoder = NULL; m_pppcBinCoderCABAC = NULL; m_statData = NULL; m_preDBFstatData = NULL; } TEncSampleAdaptiveOffset::~TEncSampleAdaptiveOffset() { destroyEncData(); } Void TEncSampleAdaptiveOffset::createEncData(Bool isPreDBFSamplesUsed) { //cabac coder for RDO m_pppcRDSbacCoder = new TEncSbac* [NUM_SAO_CABACSTATE_LABELS]; #if FAST_BIT_EST m_pppcBinCoderCABAC = new TEncBinCABACCounter* [NUM_SAO_CABACSTATE_LABELS]; #else m_pppcBinCoderCABAC = new TEncBinCABAC* [NUM_SAO_CABACSTATE_LABELS]; #endif for(Int cs=0; cs < NUM_SAO_CABACSTATE_LABELS; cs++) { m_pppcRDSbacCoder[cs] = new TEncSbac; #if FAST_BIT_EST m_pppcBinCoderCABAC[cs] = new TEncBinCABACCounter; #else m_pppcBinCoderCABAC[cs] = new TEncBinCABAC; #endif m_pppcRDSbacCoder [cs]->init( m_pppcBinCoderCABAC [cs] ); } //statistics m_statData = new SAOStatData**[m_numCTUsPic]; for(Int i=0; i< m_numCTUsPic; i++) { m_statData[i] = new SAOStatData*[MAX_NUM_COMPONENT]; for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++) { m_statData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES]; } } if(isPreDBFSamplesUsed) { m_preDBFstatData = new SAOStatData**[m_numCTUsPic]; for(Int i=0; i< m_numCTUsPic; i++) { m_preDBFstatData[i] = new SAOStatData*[MAX_NUM_COMPONENT]; for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++) { m_preDBFstatData[i][compIdx] = new SAOStatData[NUM_SAO_NEW_TYPES]; } } } ::memset(m_saoDisabledRate, 0, sizeof(m_saoDisabledRate)); for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++) { m_skipLinesR[COMPONENT_Y ][typeIdc]= 5; m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3; m_skipLinesB[COMPONENT_Y ][typeIdc]= 4; m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2; if(isPreDBFSamplesUsed) { switch(typeIdc) { case SAO_TYPE_EO_0: { m_skipLinesR[COMPONENT_Y ][typeIdc]= 5; m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3; m_skipLinesB[COMPONENT_Y ][typeIdc]= 3; m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1; } break; case SAO_TYPE_EO_90: { m_skipLinesR[COMPONENT_Y ][typeIdc]= 4; m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2; m_skipLinesB[COMPONENT_Y ][typeIdc]= 4; m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2; } break; case SAO_TYPE_EO_135: case SAO_TYPE_EO_45: { m_skipLinesR[COMPONENT_Y ][typeIdc]= 5; m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 3; m_skipLinesB[COMPONENT_Y ][typeIdc]= 4; m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 2; } break; case SAO_TYPE_BO: { m_skipLinesR[COMPONENT_Y ][typeIdc]= 4; m_skipLinesR[COMPONENT_Cb][typeIdc]= m_skipLinesR[COMPONENT_Cr][typeIdc]= 2; m_skipLinesB[COMPONENT_Y ][typeIdc]= 3; m_skipLinesB[COMPONENT_Cb][typeIdc]= m_skipLinesB[COMPONENT_Cr][typeIdc]= 1; } break; default: { printf("Not a supported type"); assert(0); exit(-1); } } } } } Void TEncSampleAdaptiveOffset::destroyEncData() { if(m_pppcRDSbacCoder != NULL) { for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ ) { delete m_pppcRDSbacCoder[cs]; } delete[] m_pppcRDSbacCoder; m_pppcRDSbacCoder = NULL; } if(m_pppcBinCoderCABAC != NULL) { for (Int cs = 0; cs < NUM_SAO_CABACSTATE_LABELS; cs ++ ) { delete m_pppcBinCoderCABAC[cs]; } delete[] m_pppcBinCoderCABAC; m_pppcBinCoderCABAC = NULL; } if(m_statData != NULL) { for(Int i=0; i< m_numCTUsPic; i++) { for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++) { delete[] m_statData[i][compIdx]; } delete[] m_statData[i]; } delete[] m_statData; m_statData = NULL; } if(m_preDBFstatData != NULL) { for(Int i=0; i< m_numCTUsPic; i++) { for(Int compIdx=0; compIdx< MAX_NUM_COMPONENT; compIdx++) { delete[] m_preDBFstatData[i][compIdx]; } delete[] m_preDBFstatData[i]; } delete[] m_preDBFstatData; m_preDBFstatData = NULL; } } Void TEncSampleAdaptiveOffset::initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice) { m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder; m_pcRDGoOnSbacCoder->resetEntropy(pcSlice); m_pcRDGoOnSbacCoder->resetBits(); m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[SAO_CABACSTATE_PIC_INIT]); } Void TEncSampleAdaptiveOffset::SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool isPreDBFSamplesUsed ) { TComPicYuv* orgYuv= pPic->getPicYuvOrg(); TComPicYuv* resYuv= pPic->getPicYuvRec(); memcpy(m_lambda, lambdas, sizeof(m_lambda)); TComPicYuv* srcYuv = m_tempPicYuv; resYuv->copyToPic(srcYuv); srcYuv->setBorderExtension(false); srcYuv->extendPicBorder(); //collect statistics getStatistics(m_statData, orgYuv, srcYuv, pPic); if(isPreDBFSamplesUsed) { addPreDBFStatistics(m_statData); } //slice on/off decidePicParams(sliceEnabled, pPic, saoEncodingRate, saoEncodingRateChroma); //block on/off SAOBlkParam* reconParams = new SAOBlkParam[m_numCTUsPic]; //temporary parameter buffer for storing reconstructed SAO parameters decideBlkParams(pPic, sliceEnabled, m_statData, srcYuv, resYuv, reconParams, pPic->getPicSym()->getSAOBlkParam(), bTestSAODisableAtPictureLevel, saoEncodingRate, saoEncodingRateChroma); delete[] reconParams; } Void TEncSampleAdaptiveOffset::getPreDBFStatistics(TComPic* pPic) { getStatistics(m_preDBFstatData, pPic->getPicYuvOrg(), pPic->getPicYuvRec(), pPic, true); } Void TEncSampleAdaptiveOffset::addPreDBFStatistics(SAOStatData*** blkStats) { for(Int n=0; n< m_numCTUsPic; n++) { for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++) { for(Int typeIdc=0; typeIdc < NUM_SAO_NEW_TYPES; typeIdc++) { blkStats[n][compIdx][typeIdc] += m_preDBFstatData[n][compIdx][typeIdc]; } } } } Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic, Bool isCalculatePreDeblockSamples) { Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail; const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for(Int ctuRsAddr= 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++) { Int yPos = (ctuRsAddr / m_numCTUInWidth)*m_maxCUHeight; Int xPos = (ctuRsAddr % m_numCTUInWidth)*m_maxCUWidth; Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight; Int width = (xPos + m_maxCUWidth > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth; pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctuRsAddr, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail); //NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities. //For simplicity, here only picture boundaries are considered. isRightAvail = (xPos + m_maxCUWidth < m_picWidth ); isBelowAvail = (yPos + m_maxCUHeight < m_picHeight); isBelowRightAvail = (isRightAvail && isBelowAvail); isBelowLeftAvail = ((xPos > 0) && (isBelowAvail)); isAboveRightAvail = ((yPos > 0) && (isRightAvail)); for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { const ComponentID component = ComponentID(compIdx); const UInt componentScaleX = getComponentScaleX(component, pPic->getChromaFormat()); const UInt componentScaleY = getComponentScaleY(component, pPic->getChromaFormat()); Int srcStride = srcYuv->getStride(component); Pel* srcBlk = srcYuv->getAddr(component) + ((yPos >> componentScaleY) * srcStride) + (xPos >> componentScaleX); Int orgStride = orgYuv->getStride(component); Pel* orgBlk = orgYuv->getAddr(component) + ((yPos >> componentScaleY) * orgStride) + (xPos >> componentScaleX); getBlkStats(component, pPic->getPicSym()->getSPS().getBitDepth(toChannelType(component)), blkStats[ctuRsAddr][component] , srcBlk, orgBlk, srcStride, orgStride, (width >> componentScaleX), (height >> componentScaleY) , isLeftAvail, isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail , isCalculatePreDeblockSamples ); } } } Void TEncSampleAdaptiveOffset::resetEncoderDecisions() { for (Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { for (Int tempLayer = 1; tempLayer < MAX_TLAYER; tempLayer++) { m_saoDisabledRate[compIdx][tempLayer] = 0.0; } } } Void TEncSampleAdaptiveOffset::decidePicParams(Bool* sliceEnabled, const TComPic* pic, const Double saoEncodingRate, const Double saoEncodingRateChroma) { const Int picTempLayer = pic->getSlice(0)->getDepth(); //decide sliceEnabled[compIdx] const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for (Int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++) { sliceEnabled[compIdx] = false; } for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { // reset flags & counters sliceEnabled[compIdx] = true; if (saoEncodingRate>0.0) { if (saoEncodingRateChroma>0.0) { // decide slice-level on/off based on previous results if( (picTempLayer > 0) && (m_saoDisabledRate[compIdx][picTempLayer-1] > ((compIdx==COMPONENT_Y) ? saoEncodingRate : saoEncodingRateChroma)) ) { sliceEnabled[compIdx] = false; } } else { // decide slice-level on/off based on previous results if( (picTempLayer > 0) && (m_saoDisabledRate[COMPONENT_Y][0] > saoEncodingRate) ) { sliceEnabled[compIdx] = false; } } } } } Int64 TEncSampleAdaptiveOffset::getDistortion(const Int channelBitDepth, Int typeIdc, Int typeAuxInfo, Int* invQuantOffset, SAOStatData& statData) { Int64 dist = 0; Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(channelBitDepth - 8); switch(typeIdc) { case SAO_TYPE_EO_0: case SAO_TYPE_EO_90: case SAO_TYPE_EO_135: case SAO_TYPE_EO_45: { for (Int offsetIdx=0; offsetIdx> shift); } inline Int TEncSampleAdaptiveOffset::estIterOffset(Int typeIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh ) { Int iterOffset, tempOffset; Int64 tempDist, tempRate; Double tempCost, tempMinCost; Int offsetOutput = 0; iterOffset = offsetInput; // Assuming sending quantized value 0 results in zero offset and sending the value zero needs 1 bit. entropy coder can be used to measure the exact rate here. tempMinCost = lambda; while (iterOffset != 0) { // Calculate the bits required for signaling the offset tempRate = (typeIdx == SAO_TYPE_BO) ? (abs((Int)iterOffset)+2) : (abs((Int)iterOffset)+1); if (abs((Int)iterOffset)==offsetTh) //inclusive { tempRate --; } // Do the dequantization before distortion calculation tempOffset = iterOffset << bitIncrease; tempDist = estSaoDist( count, tempOffset, diffSum, shift); tempCost = ((Double)tempDist + lambda * (Double) tempRate); if(tempCost < tempMinCost) { tempMinCost = tempCost; offsetOutput = iterOffset; bestDist = tempDist; bestCost = tempCost; } iterOffset = (iterOffset > 0) ? (iterOffset-1):(iterOffset+1); } return offsetOutput; } Void TEncSampleAdaptiveOffset::deriveOffsets(ComponentID compIdx, const Int channelBitDepth, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo) { Int bitDepth = channelBitDepth; Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepth-8); Int offsetTh = TComSampleAdaptiveOffset::getMaxOffsetQVal(channelBitDepth); //inclusive ::memset(quantOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES); //derive initial offsets Int numClasses = (typeIdc == SAO_TYPE_BO)?((Int)NUM_SAO_BO_CLASSES):((Int)NUM_SAO_EO_CLASSES); for(Int classIdx=0; classIdx< numClasses; classIdx++) { if( (typeIdc != SAO_TYPE_BO) && (classIdx==SAO_CLASS_EO_PLAIN) ) { continue; //offset will be zero } if(statData.count[classIdx] == 0) { continue; //offset will be zero } quantOffsets[classIdx] = (Int) xRoundIbdi(bitDepth, (Double)( statData.diff[classIdx]<<(bitDepth-8)) / (Double)( statData.count[classIdx]<< m_offsetStepLog2[compIdx]) ); quantOffsets[classIdx] = Clip3(-offsetTh, offsetTh, quantOffsets[classIdx]); } // adjust offsets switch(typeIdc) { case SAO_TYPE_EO_0: case SAO_TYPE_EO_90: case SAO_TYPE_EO_135: case SAO_TYPE_EO_45: { Int64 classDist; Double classCost; for(Int classIdx=0; classIdx 0) { quantOffsets[classIdx] =0; } if(classIdx==SAO_CLASS_EO_FULL_PEAK && quantOffsets[classIdx] > 0) { quantOffsets[classIdx] =0; } if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero { quantOffsets[classIdx] = estIterOffset( typeIdc, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], classDist , classCost , offsetTh ); } } typeAuxInfo =0; } break; case SAO_TYPE_BO: { Int64 distBOClasses[NUM_SAO_BO_CLASSES]; Double costBOClasses[NUM_SAO_BO_CLASSES]; ::memset(distBOClasses, 0, sizeof(Int64)*NUM_SAO_BO_CLASSES); for(Int classIdx=0; classIdx< NUM_SAO_BO_CLASSES; classIdx++) { costBOClasses[classIdx]= m_lambda[compIdx]; if( quantOffsets[classIdx] != 0 ) //iterative adjustment only when derived offset is not zero { quantOffsets[classIdx] = estIterOffset( typeIdc, m_lambda[compIdx], quantOffsets[classIdx], statData.count[classIdx], statData.diff[classIdx], shift, m_offsetStepLog2[compIdx], distBOClasses[classIdx], costBOClasses[classIdx], offsetTh ); } } //decide the starting band index Double minCost = MAX_DOUBLE, cost; for(Int band=0; band< NUM_SAO_BO_CLASSES- 4+ 1; band++) { cost = costBOClasses[band ]; cost += costBOClasses[band+1]; cost += costBOClasses[band+2]; cost += costBOClasses[band+3]; if(cost < minCost) { minCost = cost; typeAuxInfo = band; } } //clear those unused classes Int clearQuantOffset[NUM_SAO_BO_CLASSES]; ::memset(clearQuantOffset, 0, sizeof(Int)*NUM_SAO_BO_CLASSES); for(Int i=0; i< 4; i++) { Int band = (typeAuxInfo+i)%NUM_SAO_BO_CLASSES; clearQuantOffset[band] = quantOffsets[band]; } ::memcpy(quantOffsets, clearQuantOffset, sizeof(Int)*NUM_SAO_BO_CLASSES); } break; default: { printf("Not a supported type"); assert(0); exit(-1); } } } Void TEncSampleAdaptiveOffset::deriveModeNewRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel) { Double minCost, cost; UInt previousWrittenBits; const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); Int64 dist[MAX_NUM_COMPONENT], modeDist[MAX_NUM_COMPONENT]; SAOOffset testOffset[MAX_NUM_COMPONENT]; Int invQuantOffset[MAX_NUM_SAO_CLASSES]; for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++) { modeDist[comp] = 0; } //pre-encode merge flags modeParam[COMPONENT_Y].modeIdc = SAO_MODE_OFF; m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), true); m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); //------ luma --------// { const ComponentID compIdx = COMPONENT_Y; //"off" case as initial cost modeParam[compIdx].modeIdc = SAO_MODE_OFF; m_pcRDGoOnSbacCoder->resetBits(); m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, modeParam[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]); modeDist[compIdx] = 0; minCost= m_lambda[compIdx]*((Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits()); m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); if(sliceEnabled[compIdx]) { for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++) { testOffset[compIdx].modeIdc = SAO_MODE_NEW; testOffset[compIdx].typeIdc = typeIdc; //derive coded offset deriveOffsets(compIdx, bitDepths.recon[CHANNEL_TYPE_LUMA], typeIdc, blkStats[ctuRsAddr][compIdx][typeIdc], testOffset[compIdx].offset, testOffset[compIdx].typeAuxInfo); //inversed quantized offsets invertQuantOffsets(compIdx, typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, testOffset[compIdx].offset); //get distortion dist[compIdx] = getDistortion(bitDepths.recon[CHANNEL_TYPE_LUMA], testOffset[compIdx].typeIdc, testOffset[compIdx].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][compIdx][typeIdc]); //get rate m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); m_pcRDGoOnSbacCoder->resetBits(); m_pcRDGoOnSbacCoder->codeSAOOffsetParam(compIdx, testOffset[compIdx], sliceEnabled[compIdx], bitDepths.recon[CHANNEL_TYPE_LUMA]); Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); cost = (Double)dist[compIdx] + m_lambda[compIdx]*((Double)rate); if(cost < minCost) { minCost = cost; modeDist[compIdx] = dist[compIdx]; modeParam[compIdx]= testOffset[compIdx]; m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); } } } m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); } //------ chroma --------// //"off" case as initial cost cost = 0; previousWrittenBits = 0; m_pcRDGoOnSbacCoder->resetBits(); for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++) { const ComponentID component = ComponentID(componentIndex); modeParam[component].modeIdc = SAO_MODE_OFF; modeDist [component] = 0; m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, modeParam[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]); const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); cost += m_lambda[component] * (currentWrittenBits - previousWrittenBits); previousWrittenBits = currentWrittenBits; } minCost = cost; //doesn't need to store cabac status here since the whole CTU parameters will be re-encoded at the end of this function for(Int typeIdc=0; typeIdc< NUM_SAO_NEW_TYPES; typeIdc++) { m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_MID]); m_pcRDGoOnSbacCoder->resetBits(); previousWrittenBits = 0; cost = 0; for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++) { const ComponentID component = ComponentID(componentIndex); if(!sliceEnabled[component]) { testOffset[component].modeIdc = SAO_MODE_OFF; dist[component]= 0; continue; } testOffset[component].modeIdc = SAO_MODE_NEW; testOffset[component].typeIdc = typeIdc; //derive offset & get distortion deriveOffsets(component, bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, blkStats[ctuRsAddr][component][typeIdc], testOffset[component].offset, testOffset[component].typeAuxInfo); invertQuantOffsets(component, typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, testOffset[component].offset); dist[component] = getDistortion(bitDepths.recon[CHANNEL_TYPE_CHROMA], typeIdc, testOffset[component].typeAuxInfo, invQuantOffset, blkStats[ctuRsAddr][component][typeIdc]); m_pcRDGoOnSbacCoder->codeSAOOffsetParam(component, testOffset[component], sliceEnabled[component], bitDepths.recon[CHANNEL_TYPE_CHROMA]); const UInt currentWrittenBits = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); cost += dist[component] + (m_lambda[component] * (currentWrittenBits - previousWrittenBits)); previousWrittenBits = currentWrittenBits; } if(cost < minCost) { minCost = cost; for(UInt componentIndex = COMPONENT_Cb; componentIndex < numberOfComponents; componentIndex++) { modeDist[componentIndex] = dist[componentIndex]; modeParam[componentIndex] = testOffset[componentIndex]; } } } // SAO_TYPE loop //----- re-gen rate & normalized cost----// modeNormCost = 0; for(UInt componentIndex = COMPONENT_Y; componentIndex < numberOfComponents; componentIndex++) { modeNormCost += (Double)modeDist[componentIndex] / m_lambda[componentIndex]; } m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); m_pcRDGoOnSbacCoder->resetBits(); m_pcRDGoOnSbacCoder->codeSAOBlkParam(modeParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false); modeNormCost += (Double)m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); } Void TEncSampleAdaptiveOffset::deriveModeMergeRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel) { modeNormCost = MAX_DOUBLE; Double cost; SAOBlkParam testBlkParam; const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++) { if(mergeList[mergeType] == NULL) { continue; } testBlkParam = *(mergeList[mergeType]); //normalized distortion Double normDist=0; for(Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { testBlkParam[compIdx].modeIdc = SAO_MODE_MERGE; testBlkParam[compIdx].typeIdc = mergeType; SAOOffset& mergedOffsetParam = (*(mergeList[mergeType]))[compIdx]; if( mergedOffsetParam.modeIdc != SAO_MODE_OFF) { //offsets have been reconstructed. Don't call inversed quantization function. normDist += (((Double)getDistortion(bitDepths.recon[toChannelType(ComponentID(compIdx))], mergedOffsetParam.typeIdc, mergedOffsetParam.typeAuxInfo, mergedOffsetParam.offset, blkStats[ctuRsAddr][compIdx][mergedOffsetParam.typeIdc])) /m_lambda[compIdx] ); } } //rate m_pcRDGoOnSbacCoder->load(cabacCoderRDO[inCabacLabel]); m_pcRDGoOnSbacCoder->resetBits(); m_pcRDGoOnSbacCoder->codeSAOBlkParam(testBlkParam, bitDepths, sliceEnabled, (mergeList[SAO_MERGE_LEFT]!= NULL), (mergeList[SAO_MERGE_ABOVE]!= NULL), false); Int rate = m_pcRDGoOnSbacCoder->getNumberOfWrittenBits(); cost = normDist+(Double)rate; if(cost < modeNormCost) { modeNormCost = cost; modeParam = testBlkParam; m_pcRDGoOnSbacCoder->store(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); } } m_pcRDGoOnSbacCoder->load(cabacCoderRDO[SAO_CABACSTATE_BLK_TEMP]); } Void TEncSampleAdaptiveOffset::decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma) { Bool allBlksDisabled = true; const Int numberOfComponents = getNumberValidComponents(m_chromaFormatIDC); for(Int compId = COMPONENT_Y; compId < numberOfComponents; compId++) { if (sliceEnabled[compId]) { allBlksDisabled = false; } } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]); SAOBlkParam modeParam; Double minCost, modeCost; Double totalCost = 0; // Used if bTestSAODisableAtPictureLevel==true for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++) { if(allBlksDisabled) { codedParams[ctuRsAddr].reset(); continue; } m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_CUR ]); //get merge list SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES] = { NULL }; getMergeList(pic, ctuRsAddr, reconParams, mergeList); minCost = MAX_DOUBLE; for(Int mode=0; mode < NUM_SAO_MODES; mode++) { switch(mode) { case SAO_MODE_OFF: { continue; //not necessary, since all-off case will be tested in SAO_MODE_NEW case. } break; case SAO_MODE_NEW: { deriveModeNewRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats, modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR); } break; case SAO_MODE_MERGE: { deriveModeMergeRDO(pic->getPicSym()->getSPS().getBitDepths(), ctuRsAddr, mergeList, sliceEnabled, blkStats , modeParam, modeCost, m_pppcRDSbacCoder, SAO_CABACSTATE_BLK_CUR); } break; default: { printf("Not a supported SAO mode\n"); assert(0); exit(-1); } } if(modeCost < minCost) { minCost = modeCost; codedParams[ctuRsAddr] = modeParam; m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]); } } //mode totalCost += minCost; m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_BLK_NEXT ]); //apply reconstructed offsets reconParams[ctuRsAddr] = codedParams[ctuRsAddr]; reconstructBlkSAOParam(reconParams[ctuRsAddr], mergeList); offsetCTU(ctuRsAddr, srcYuv, resYuv, reconParams[ctuRsAddr], pic); } //ctuRsAddr if (!allBlksDisabled && (totalCost >= 0) && bTestSAODisableAtPictureLevel) //SAO has not beneficial in this case - disable it { for(Int ctuRsAddr = 0; ctuRsAddr < m_numCTUsPic; ctuRsAddr++) { codedParams[ctuRsAddr].reset(); } for (UInt componentIndex = 0; componentIndex < MAX_NUM_COMPONENT; componentIndex++) { sliceEnabled[componentIndex] = false; } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[ SAO_CABACSTATE_PIC_INIT ]); } if (saoEncodingRate > 0.0) { Int picTempLayer = pic->getSlice(0)->getDepth(); Int numCtusForSAOOff[MAX_NUM_COMPONENT]; for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { numCtusForSAOOff[compIdx] = 0; for(Int ctuRsAddr=0; ctuRsAddr< m_numCTUsPic; ctuRsAddr++) { if( reconParams[ctuRsAddr][compIdx].modeIdc == SAO_MODE_OFF) { numCtusForSAOOff[compIdx]++; } } } if (saoEncodingRateChroma > 0.0) { for (Int compIdx = 0; compIdx < numberOfComponents; compIdx++) { m_saoDisabledRate[compIdx][picTempLayer] = (Double)numCtusForSAOOff[compIdx]/(Double)m_numCTUsPic; } } else if (picTempLayer == 0) { m_saoDisabledRate[COMPONENT_Y][0] = (Double)(numCtusForSAOOff[COMPONENT_Y]+numCtusForSAOOff[COMPONENT_Cb]+numCtusForSAOOff[COMPONENT_Cr])/(Double)(m_numCTUsPic*3); } } } Void TEncSampleAdaptiveOffset::getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData* statsDataTypes , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height , Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail , Bool isCalculatePreDeblockSamples ) { if(m_lineBufWidth != m_maxCUWidth) { m_lineBufWidth = m_maxCUWidth; if (m_signLineBuf1) { delete[] m_signLineBuf1; m_signLineBuf1 = NULL; } m_signLineBuf1 = new SChar[m_lineBufWidth+1]; if (m_signLineBuf2) { delete[] m_signLineBuf2; m_signLineBuf2 = NULL; } m_signLineBuf2 = new SChar[m_lineBufWidth+1]; } Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX; SChar signLeft, signRight, signDown; Int64 *diff, *count; Pel *srcLine, *orgLine; Int* skipLinesR = m_skipLinesR[compIdx]; Int* skipLinesB = m_skipLinesB[compIdx]; for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++) { SAOStatData& statsData= statsDataTypes[typeIdx]; statsData.reset(); srcLine = srcBlk; orgLine = orgBlk; diff = statsData.diff; count = statsData.count; switch(typeIdx) { case SAO_TYPE_EO_0: { diff +=2; count+=2; endY = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height; startX = (!isCalculatePreDeblockSamples) ? (isLeftAvail ? 0 : 1) : (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) ; endX = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)) : (isRightAvail ? width : (width - 1)) ; for (y=0; y> shiftBits; diff [bandIdx] += (orgLine[x] - srcLine[x]); count[bandIdx] ++; } srcLine += srcStride; orgLine += orgStride; } if(isCalculatePreDeblockSamples) { if(isBelowAvail) { startX = 0; endX = width; for(y= 0; y< skipLinesB[typeIdx]; y++) { for (x=startX; x< endX; x++) { Int bandIdx= srcLine[x] >> shiftBits; diff [bandIdx] += (orgLine[x] - srcLine[x]); count[bandIdx] ++; } srcLine += srcStride; orgLine += orgStride; } } } } break; default: { printf("Not a supported SAO types\n"); assert(0); exit(-1); } } } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncSampleAdaptiveOffset.h000066400000000000000000000150571442026013100234020ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSampleAdaptiveOffset.h \brief estimation part of sample adaptive offset class (header) */ #ifndef __TENCSAMPLEADAPTIVEOFFSET__ #define __TENCSAMPLEADAPTIVEOFFSET__ #include "TLibCommon/TComSampleAdaptiveOffset.h" #include "TLibCommon/TComPic.h" #include "TEncEntropy.h" #include "TEncSbac.h" #include "TLibCommon/TComBitCounter.h" //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== enum SAOCabacStateLablesRDO //CABAC state labels { SAO_CABACSTATE_PIC_INIT =0, SAO_CABACSTATE_BLK_CUR, SAO_CABACSTATE_BLK_NEXT, SAO_CABACSTATE_BLK_MID, SAO_CABACSTATE_BLK_TEMP, NUM_SAO_CABACSTATE_LABELS }; struct SAOStatData //data structure for SAO statistics { Int64 diff[MAX_NUM_SAO_CLASSES]; Int64 count[MAX_NUM_SAO_CLASSES]; SAOStatData(){} ~SAOStatData(){} Void reset() { ::memset(diff, 0, sizeof(Int64)*MAX_NUM_SAO_CLASSES); ::memset(count, 0, sizeof(Int64)*MAX_NUM_SAO_CLASSES); } const SAOStatData& operator=(const SAOStatData& src) { ::memcpy(diff, src.diff, sizeof(Int64)*MAX_NUM_SAO_CLASSES); ::memcpy(count, src.count, sizeof(Int64)*MAX_NUM_SAO_CLASSES); return *this; } const SAOStatData& operator+= (const SAOStatData& src) { for(Int i=0; i< MAX_NUM_SAO_CLASSES; i++) { diff[i] += src.diff[i]; count[i] += src.count[i]; } return *this; } }; class TEncSampleAdaptiveOffset : public TComSampleAdaptiveOffset { public: TEncSampleAdaptiveOffset(); virtual ~TEncSampleAdaptiveOffset(); //interface Void createEncData(Bool isPreDBFSamplesUsed); Void destroyEncData(); Void initRDOCabacCoder(TEncSbac* pcRDGoOnSbacCoder, TComSlice* pcSlice) ; Void resetEncoderDecisions(); Void SAOProcess(TComPic* pPic, Bool* sliceEnabled, const Double *lambdas, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma, const Bool isPreDBFSamplesUsed); public: //methods Void getPreDBFStatistics(TComPic* pPic); private: //methods Void getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv,TComPic* pPic, Bool isCalculatePreDeblockSamples = false); Void decidePicParams(Bool* sliceEnabled, const TComPic* pic, const Double saoEncodingRate, const Double saoEncodingRateChroma); Void decideBlkParams(TComPic* pic, Bool* sliceEnabled, SAOStatData*** blkStats, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam* reconParams, SAOBlkParam* codedParams, const Bool bTestSAODisableAtPictureLevel, const Double saoEncodingRate, const Double saoEncodingRateChroma); Void getBlkStats(const ComponentID compIdx, const Int channelBitDepth, SAOStatData* statsDataTypes, Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height, Bool isLeftAvail, Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isCalculatePreDeblockSamples); Void deriveModeNewRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel); Void deriveModeMergeRDO(const BitDepths &bitDepths, Int ctuRsAddr, SAOBlkParam* mergeList[NUM_SAO_MERGE_TYPES], Bool* sliceEnabled, SAOStatData*** blkStats, SAOBlkParam& modeParam, Double& modeNormCost, TEncSbac** cabacCoderRDO, Int inCabacLabel); Int64 getDistortion(const Int channelBitDepth, Int typeIdc, Int typeAuxInfo, Int* offsetVal, SAOStatData& statData); Void deriveOffsets(ComponentID compIdx, const Int channelBitDepth, Int typeIdc, SAOStatData& statData, Int* quantOffsets, Int& typeAuxInfo); inline Int64 estSaoDist(Int64 count, Int64 offset, Int64 diffSum, Int shift); inline Int estIterOffset(Int typeIdx, Double lambda, Int offsetInput, Int64 count, Int64 diffSum, Int shift, Int bitIncrease, Int64& bestDist, Double& bestCost, Int offsetTh ); Void addPreDBFStatistics(SAOStatData*** blkStats); private: //members //for RDO TEncSbac** m_pppcRDSbacCoder; TEncSbac* m_pcRDGoOnSbacCoder; #if FAST_BIT_EST TEncBinCABACCounter** m_pppcBinCoderCABAC; #else TEncBinCABAC** m_pppcBinCoderCABAC; #endif Double m_lambda[MAX_NUM_COMPONENT]; //statistics SAOStatData*** m_statData; //[ctu][comp][classes] SAOStatData*** m_preDBFstatData; Double m_saoDisabledRate[MAX_NUM_COMPONENT][MAX_TLAYER]; Int m_skipLinesR[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES]; Int m_skipLinesB[MAX_NUM_COMPONENT][NUM_SAO_NEW_TYPES]; }; //! \} #endif HM-HM-18.0/source/Lib/TLibEncoder/TEncSbac.cpp000066400000000000000000002150131442026013100205310ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSbac.cpp \brief SBAC encoder class */ #include "TEncTop.h" #include "TEncSbac.h" #include "TLibCommon/TComTU.h" #include #include #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST #include "../TLibCommon/Debug.h" #endif //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TEncSbac::TEncSbac() // new structure here : m_pcBitIf ( NULL ) , m_pcBinIf ( NULL ) , m_numContextModels ( 0 ) , m_cCUSplitFlagSCModel ( 1, 1, NUM_SPLIT_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSkipFlagSCModel ( 1, 1, NUM_SKIP_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMergeFlagExtSCModel ( 1, 1, NUM_MERGE_FLAG_EXT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMergeIdxExtSCModel ( 1, 1, NUM_MERGE_IDX_EXT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUPartSizeSCModel ( 1, 1, NUM_PART_SIZE_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUPredModeSCModel ( 1, 1, NUM_PRED_MODE_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUIntraPredSCModel ( 1, 1, NUM_INTRA_PREDICT_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUChromaPredSCModel ( 1, 1, NUM_CHROMA_PRED_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUDeltaQpSCModel ( 1, 1, NUM_DELTA_QP_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUInterDirSCModel ( 1, 1, NUM_INTER_DIR_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCURefPicSCModel ( 1, 1, NUM_REF_NO_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMvdSCModel ( 1, 1, NUM_MV_RES_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtCbfSCModel ( 1, NUM_QT_CBF_CTX_SETS, NUM_QT_CBF_CTX_PER_SET , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUTransSubdivFlagSCModel ( 1, 1, NUM_TRANS_SUBDIV_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtRootCbfSCModel ( 1, 1, NUM_QT_ROOT_CBF_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigCoeffGroupSCModel ( 1, 2, NUM_SIG_CG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigSCModel ( 1, 1, NUM_SIG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastX ( 1, NUM_CTX_LAST_FLAG_SETS, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastY ( 1, NUM_CTX_LAST_FLAG_SETS, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUOneSCModel ( 1, 1, NUM_ONE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUAbsSCModel ( 1, 1, NUM_ABS_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cMVPIdxSCModel ( 1, 1, NUM_MVP_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoMergeSCModel ( 1, 1, NUM_SAO_MERGE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoTypeIdxSCModel ( 1, 1, NUM_SAO_TYPE_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cTransformSkipSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_TRANSFORMSKIP_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_CUTransquantBypassFlagSCModel ( 1, 1, NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_explicitRdpcmFlagSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_EXPLICIT_RDPCM_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_explicitRdpcmDirSCModel ( 1, MAX_NUM_CHANNEL_TYPE, NUM_EXPLICIT_RDPCM_DIR_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCrossComponentPredictionSCModel ( 1, 1, NUM_CROSS_COMPONENT_PREDICTION_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_ChromaQpAdjFlagSCModel ( 1, 1, NUM_CHROMA_QP_ADJ_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_ChromaQpAdjIdcSCModel ( 1, 1, NUM_CHROMA_QP_ADJ_IDC_CTX , m_contextModels + m_numContextModels, m_numContextModels) { assert( m_numContextModels <= MAX_NUM_CTX_MOD ); } TEncSbac::~TEncSbac() { } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TEncSbac::resetEntropy (const TComSlice *pSlice) { Int iQp = pSlice->getSliceQp(); SliceType eSliceType = pSlice->getSliceType(); SliceType encCABACTableIdx = pSlice->getEncCABACTableIdx(); if (!pSlice->isIntra() && (encCABACTableIdx==B_SLICE || encCABACTableIdx==P_SLICE) && pSlice->getPPS()->getCabacInitPresentFlag()) { eSliceType = encCABACTableIdx; } m_cCUSplitFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SPLIT_FLAG ); m_cCUSkipFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SKIP_FLAG ); m_cCUMergeFlagExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_FLAG_EXT); m_cCUMergeIdxExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_IDX_EXT); m_cCUPartSizeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_PART_SIZE ); m_cCUPredModeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_PRED_MODE ); m_cCUIntraPredSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_INTRA_PRED_MODE ); m_cCUChromaPredSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CHROMA_PRED_MODE ); m_cCUInterDirSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_INTER_DIR ); m_cCUMvdSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MVD ); m_cCURefPicSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_REF_PIC ); m_cCUDeltaQpSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_DQP ); m_cCUQtCbfSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_QT_CBF ); m_cCUQtRootCbfSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_QT_ROOT_CBF ); m_cCUSigCoeffGroupSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SIG_CG_FLAG ); m_cCUSigSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SIG_FLAG ); m_cCuCtxLastX.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); m_cCuCtxLastY.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); m_cCUOneSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ONE_FLAG ); m_cCUAbsSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ABS_FLAG ); m_cMVPIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MVP_IDX ); m_cCUTransSubdivFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANS_SUBDIV_FLAG ); m_cSaoMergeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_MERGE_FLAG ); m_cSaoTypeIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_TYPE_IDX ); m_cTransformSkipSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANSFORMSKIP_FLAG ); m_CUTransquantBypassFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG ); m_explicitRdpcmFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_EXPLICIT_RDPCM_FLAG); m_explicitRdpcmDirSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_EXPLICIT_RDPCM_DIR); m_cCrossComponentPredictionSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CROSS_COMPONENT_PREDICTION ); m_ChromaQpAdjFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CHROMA_QP_ADJ_FLAG ); m_ChromaQpAdjIdcSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CHROMA_QP_ADJ_IDC ); for (UInt statisticIndex = 0; statisticIndex < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS ; statisticIndex++) { m_golombRiceAdaptationStatistics[statisticIndex] = 0; } m_pcBinIf->start(); return; } /** The function does the following: * If current slice type is P/B then it determines the distance of initialisation type 1 and 2 from the current CABAC states and * stores the index of the closest table. This index is used for the next P/B slice when cabac_init_present_flag is true. */ SliceType TEncSbac::determineCabacInitIdx(const TComSlice *pSlice) { Int qp = pSlice->getSliceQp(); if (!pSlice->isIntra()) { SliceType aSliceTypeChoices[] = {B_SLICE, P_SLICE}; UInt bestCost = MAX_UINT; SliceType bestSliceType = aSliceTypeChoices[0]; for (UInt idx=0; idx<2; idx++) { UInt curCost = 0; SliceType curSliceType = aSliceTypeChoices[idx]; curCost = m_cCUSplitFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SPLIT_FLAG ); curCost += m_cCUSkipFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SKIP_FLAG ); curCost += m_cCUMergeFlagExtSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_MERGE_FLAG_EXT); curCost += m_cCUMergeIdxExtSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_MERGE_IDX_EXT); curCost += m_cCUPartSizeSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_PART_SIZE ); curCost += m_cCUPredModeSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_PRED_MODE ); curCost += m_cCUIntraPredSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_INTRA_PRED_MODE ); curCost += m_cCUChromaPredSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_CHROMA_PRED_MODE ); curCost += m_cCUInterDirSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_INTER_DIR ); curCost += m_cCUMvdSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_MVD ); curCost += m_cCURefPicSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_REF_PIC ); curCost += m_cCUDeltaQpSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_DQP ); curCost += m_cCUQtCbfSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_QT_CBF ); curCost += m_cCUQtRootCbfSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_QT_ROOT_CBF ); curCost += m_cCUSigCoeffGroupSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SIG_CG_FLAG ); curCost += m_cCUSigSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SIG_FLAG ); curCost += m_cCuCtxLastX.calcCost ( curSliceType, qp, (UChar*)INIT_LAST ); curCost += m_cCuCtxLastY.calcCost ( curSliceType, qp, (UChar*)INIT_LAST ); curCost += m_cCUOneSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_ONE_FLAG ); curCost += m_cCUAbsSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_ABS_FLAG ); curCost += m_cMVPIdxSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_MVP_IDX ); curCost += m_cCUTransSubdivFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_TRANS_SUBDIV_FLAG ); curCost += m_cSaoMergeSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SAO_MERGE_FLAG ); curCost += m_cSaoTypeIdxSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_SAO_TYPE_IDX ); curCost += m_cTransformSkipSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_TRANSFORMSKIP_FLAG ); curCost += m_CUTransquantBypassFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG ); curCost += m_explicitRdpcmFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_FLAG); curCost += m_explicitRdpcmDirSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_DIR); curCost += m_cCrossComponentPredictionSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_CROSS_COMPONENT_PREDICTION ); curCost += m_ChromaQpAdjFlagSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_FLAG ); curCost += m_ChromaQpAdjIdcSCModel.calcCost ( curSliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_IDC ); if (curCost < bestCost) { bestSliceType = curSliceType; bestCost = curCost; } } return bestSliceType; } else { return I_SLICE; } } Void TEncSbac::codeVPS( const TComVPS* /*pcVPS*/ ) { assert (0); return; } Void TEncSbac::codeSPS( const TComSPS* /*pcSPS*/ ) { assert (0); return; } Void TEncSbac::codePPS( const TComPPS* /*pcPPS*/ ) { assert (0); return; } Void TEncSbac::codeSliceHeader( TComSlice* /*pcSlice*/ ) { assert (0); return; } Void TEncSbac::codeTilesWPPEntryPoint( TComSlice* /*pSlice*/ ) { assert (0); return; } Void TEncSbac::codeTerminatingBit( UInt uilsLast ) { m_pcBinIf->encodeBinTrm( uilsLast ); } Void TEncSbac::codeSliceFinish() { m_pcBinIf->finish(); } Void TEncSbac::xWriteUnarySymbol( UInt uiSymbol, ContextModel* pcSCModel, Int iOffset ) { m_pcBinIf->encodeBin( uiSymbol ? 1 : 0, pcSCModel[0] ); if( 0 == uiSymbol) { return; } while( uiSymbol-- ) { m_pcBinIf->encodeBin( uiSymbol ? 1 : 0, pcSCModel[ iOffset ] ); } return; } Void TEncSbac::xWriteUnaryMaxSymbol( UInt uiSymbol, ContextModel* pcSCModel, Int iOffset, UInt uiMaxSymbol ) { if (uiMaxSymbol == 0) { return; } m_pcBinIf->encodeBin( uiSymbol ? 1 : 0, pcSCModel[ 0 ] ); if ( uiSymbol == 0 ) { return; } Bool bCodeLast = ( uiMaxSymbol > uiSymbol ); while( --uiSymbol ) { m_pcBinIf->encodeBin( 1, pcSCModel[ iOffset ] ); } if( bCodeLast ) { m_pcBinIf->encodeBin( 0, pcSCModel[ iOffset ] ); } return; } Void TEncSbac::xWriteEpExGolomb( UInt uiSymbol, UInt uiCount ) { UInt bins = 0; Int numBins = 0; while( uiSymbol >= (UInt)(1<encodeBinsEP( bins, numBins ); } /** Coding of coeff_abs_level_minus3 * \param symbol value of coeff_abs_level_minus3 * \param rParam reference to Rice parameter * \param useLimitedPrefixLength * \param maxLog2TrDynamicRange */ Void TEncSbac::xWriteCoefRemainExGolomb ( UInt symbol, UInt &rParam, const Bool useLimitedPrefixLength, const Int maxLog2TrDynamicRange ) { Int codeNumber = (Int)symbol; UInt length; if (codeNumber < (COEF_REMAIN_BIN_REDUCTION << rParam)) { length = codeNumber>>rParam; m_pcBinIf->encodeBinsEP( (1<<(length+1))-2 , length+1); m_pcBinIf->encodeBinsEP((codeNumber%(1<> rParam) - COEF_REMAIN_BIN_REDUCTION; if (codeValue >= ((1 << maximumPrefixLength) - 1)) { prefixLength = maximumPrefixLength; suffixLength = maxLog2TrDynamicRange - rParam; } else { while (codeValue > ((2 << prefixLength) - 2)) { prefixLength++; } suffixLength = prefixLength + 1; //+1 for the separator bit } const UInt suffix = codeValue - ((1 << prefixLength) - 1); const UInt totalPrefixLength = prefixLength + COEF_REMAIN_BIN_REDUCTION; const UInt prefix = (1 << totalPrefixLength) - 1; const UInt rParamBitMask = (1 << rParam) - 1; m_pcBinIf->encodeBinsEP( prefix, totalPrefixLength ); //prefix m_pcBinIf->encodeBinsEP(((suffix << rParam) | (symbol & rParamBitMask)), (suffixLength + rParam)); //separator, suffix, and rParam bits } else { length = rParam; codeNumber = codeNumber - ( COEF_REMAIN_BIN_REDUCTION << rParam); while (codeNumber >= (1<encodeBinsEP((1<<(COEF_REMAIN_BIN_REDUCTION+length+1-rParam))-2,COEF_REMAIN_BIN_REDUCTION+length+1-rParam); m_pcBinIf->encodeBinsEP(codeNumber,length); } } // SBAC RD Void TEncSbac::load ( const TEncSbac* pSrc) { this->xCopyFrom(pSrc); } Void TEncSbac::loadIntraDirMode( const TEncSbac* pSrc, const ChannelType chType ) { m_pcBinIf->copyState( pSrc->m_pcBinIf ); if (isLuma(chType)) { this->m_cCUIntraPredSCModel .copyFrom( &pSrc->m_cCUIntraPredSCModel ); } else { this->m_cCUChromaPredSCModel .copyFrom( &pSrc->m_cCUChromaPredSCModel ); } } Void TEncSbac::store( TEncSbac* pDest) const { pDest->xCopyFrom( this ); } Void TEncSbac::xCopyFrom( const TEncSbac* pSrc ) { m_pcBinIf->copyState( pSrc->m_pcBinIf ); xCopyContextsFrom(pSrc); } Void TEncSbac::codeMVPIdx ( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { Int iSymbol = pcCU->getMVPIdx(eRefList, uiAbsPartIdx); Int iNum = AMVP_MAX_NUM_CANDS; xWriteUnaryMaxSymbol(iSymbol, m_cMVPIdxSCModel.get(0), 1, iNum-1); } Void TEncSbac::codePartSize( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { PartSize eSize = pcCU->getPartitionSize( uiAbsPartIdx ); const UInt log2DiffMaxMinCodingBlockSize = pcCU->getSlice()->getSPS()->getLog2DiffMaxMinCodingBlockSize(); if ( pcCU->isIntra( uiAbsPartIdx ) ) { if( uiDepth == log2DiffMaxMinCodingBlockSize ) { m_pcBinIf->encodeBin( eSize == SIZE_2Nx2N? 1 : 0, m_cCUPartSizeSCModel.get( 0, 0, 0 ) ); } return; } switch(eSize) { case SIZE_2Nx2N: { m_pcBinIf->encodeBin( 1, m_cCUPartSizeSCModel.get( 0, 0, 0) ); break; } case SIZE_2NxN: case SIZE_2NxnU: case SIZE_2NxnD: { m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 0) ); m_pcBinIf->encodeBin( 1, m_cCUPartSizeSCModel.get( 0, 0, 1) ); if ( pcCU->getSlice()->getSPS()->getUseAMP() && uiDepth < log2DiffMaxMinCodingBlockSize ) { if (eSize == SIZE_2NxN) { m_pcBinIf->encodeBin(1, m_cCUPartSizeSCModel.get( 0, 0, 3 )); } else { m_pcBinIf->encodeBin(0, m_cCUPartSizeSCModel.get( 0, 0, 3 )); m_pcBinIf->encodeBinEP((eSize == SIZE_2NxnU? 0: 1)); } } break; } case SIZE_Nx2N: case SIZE_nLx2N: case SIZE_nRx2N: { m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 0) ); m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 1) ); if( uiDepth == log2DiffMaxMinCodingBlockSize && !( pcCU->getWidth(uiAbsPartIdx) == 8 && pcCU->getHeight(uiAbsPartIdx) == 8 ) ) { m_pcBinIf->encodeBin( 1, m_cCUPartSizeSCModel.get( 0, 0, 2) ); } if ( pcCU->getSlice()->getSPS()->getUseAMP() && uiDepth < log2DiffMaxMinCodingBlockSize ) { if (eSize == SIZE_Nx2N) { m_pcBinIf->encodeBin(1, m_cCUPartSizeSCModel.get( 0, 0, 3 )); } else { m_pcBinIf->encodeBin(0, m_cCUPartSizeSCModel.get( 0, 0, 3 )); m_pcBinIf->encodeBinEP((eSize == SIZE_nLx2N? 0: 1)); } } break; } case SIZE_NxN: { if( uiDepth == log2DiffMaxMinCodingBlockSize && !( pcCU->getWidth(uiAbsPartIdx) == 8 && pcCU->getHeight(uiAbsPartIdx) == 8 ) ) { m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 0) ); m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 1) ); m_pcBinIf->encodeBin( 0, m_cCUPartSizeSCModel.get( 0, 0, 2) ); } break; } default: { assert(0); break; } } } /** code prediction mode * \param pcCU * \param uiAbsPartIdx * \returns Void */ Void TEncSbac::codePredMode( TComDataCU* pcCU, UInt uiAbsPartIdx ) { // get context function is here m_pcBinIf->encodeBin( pcCU->isIntra( uiAbsPartIdx ) ? 1 : 0, m_cCUPredModeSCModel.get( 0, 0, 0 ) ); } Void TEncSbac::codeCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiSymbol = pcCU->getCUTransquantBypass(uiAbsPartIdx); m_pcBinIf->encodeBin( uiSymbol, m_CUTransquantBypassFlagSCModel.get( 0, 0, 0 ) ); } /** code skip flag * \param pcCU * \param uiAbsPartIdx * \returns Void */ Void TEncSbac::codeSkipFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) { // get context function is here UInt uiSymbol = pcCU->isSkipped( uiAbsPartIdx ) ? 1 : 0; UInt uiCtxSkip = pcCU->getCtxSkipFlag( uiAbsPartIdx ) ; m_pcBinIf->encodeBin( uiSymbol, m_cCUSkipFlagSCModel.get( 0, 0, uiCtxSkip ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tSkipFlag" ); DTRACE_CABAC_T( "\tuiCtxSkip: "); DTRACE_CABAC_V( uiCtxSkip ); DTRACE_CABAC_T( "\tuiSymbol: "); DTRACE_CABAC_V( uiSymbol ); DTRACE_CABAC_T( "\n"); } /** code merge flag * \param pcCU * \param uiAbsPartIdx * \returns Void */ Void TEncSbac::codeMergeFlag( TComDataCU* pcCU, UInt uiAbsPartIdx ) { const UInt uiSymbol = pcCU->getMergeFlag( uiAbsPartIdx ) ? 1 : 0; m_pcBinIf->encodeBin( uiSymbol, *m_cCUMergeFlagExtSCModel.get( 0 ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tMergeFlag: " ); DTRACE_CABAC_V( uiSymbol ); DTRACE_CABAC_T( "\tAddress: " ); DTRACE_CABAC_V( pcCU->getCtuRsAddr() ); DTRACE_CABAC_T( "\tuiAbsPartIdx: " ); DTRACE_CABAC_V( uiAbsPartIdx ); DTRACE_CABAC_T( "\n" ); } /** code merge index * \param pcCU * \param uiAbsPartIdx * \returns Void */ Void TEncSbac::codeMergeIndex( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiUnaryIdx = pcCU->getMergeIndex( uiAbsPartIdx ); UInt uiNumCand = pcCU->getSlice()->getMaxNumMergeCand(); if ( uiNumCand > 1 ) { for( UInt ui = 0; ui < uiNumCand - 1; ++ui ) { const UInt uiSymbol = ui == uiUnaryIdx ? 0 : 1; if ( ui==0 ) { m_pcBinIf->encodeBin( uiSymbol, m_cCUMergeIdxExtSCModel.get( 0, 0, 0 ) ); } else { m_pcBinIf->encodeBinEP( uiSymbol ); } if( uiSymbol == 0 ) { break; } } } DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tparseMergeIndex()" ); DTRACE_CABAC_T( "\tuiMRGIdx= " ); DTRACE_CABAC_V( pcCU->getMergeIndex( uiAbsPartIdx ) ); DTRACE_CABAC_T( "\n" ); } Void TEncSbac::codeSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) { if( uiDepth == pcCU->getSlice()->getSPS()->getLog2DiffMaxMinCodingBlockSize() ) { return; } UInt uiCtx = pcCU->getCtxSplitFlag( uiAbsPartIdx, uiDepth ); UInt uiCurrSplitFlag = ( pcCU->getDepth( uiAbsPartIdx ) > uiDepth ) ? 1 : 0; assert( uiCtx < 3 ); m_pcBinIf->encodeBin( uiCurrSplitFlag, m_cCUSplitFlagSCModel.get( 0, 0, uiCtx ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tSplitFlag\n" ) return; } Void TEncSbac::codeTransformSubdivFlag( UInt uiSymbol, UInt uiCtx ) { m_pcBinIf->encodeBin( uiSymbol, m_cCUTransSubdivFlagSCModel.get( 0, 0, uiCtx ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseTransformSubdivFlag()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiSymbol ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\n" ) } Void TEncSbac::codeIntraDirLumaAng( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiple) { UInt dir[4],j; Int preds[4][NUM_MOST_PROBABLE_MODES] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}}; Int predIdx[4] ={ -1,-1,-1,-1}; PartSize mode = pcCU->getPartitionSize( absPartIdx ); UInt partNum = isMultiple?(mode==SIZE_NxN?4:1):1; UInt partOffset = ( pcCU->getPic()->getNumPartitionsInCtu() >> ( pcCU->getDepth(absPartIdx) << 1 ) ) >> 2; for (j=0;jgetIntraDir( CHANNEL_TYPE_LUMA, absPartIdx+partOffset*j ); pcCU->getIntraDirPredictor(absPartIdx+partOffset*j, preds[j], COMPONENT_Y); for(UInt i = 0; i < NUM_MOST_PROBABLE_MODES; i++) { if(dir[j] == preds[j][i]) { predIdx[j] = i; } } m_pcBinIf->encodeBin((predIdx[j] != -1)? 1 : 0, m_cCUIntraPredSCModel.get( 0, 0, 0 ) ); } for (j=0;jencodeBinEP( predIdx[j] ? 1 : 0 ); if (predIdx[j]) { m_pcBinIf->encodeBinEP( predIdx[j]-1 ); } } else { if (preds[j][0] > preds[j][1]) { std::swap(preds[j][0], preds[j][1]); } if (preds[j][0] > preds[j][2]) { std::swap(preds[j][0], preds[j][2]); } if (preds[j][1] > preds[j][2]) { std::swap(preds[j][1], preds[j][2]); } for(Int i = (Int(NUM_MOST_PROBABLE_MODES) - 1); i >= 0; i--) { dir[j] = dir[j] > preds[j][i] ? dir[j] - 1 : dir[j]; } m_pcBinIf->encodeBinsEP( dir[j], 5 ); } } return; } Void TEncSbac::codeIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiIntraDirChroma = pcCU->getIntraDir( CHANNEL_TYPE_CHROMA, uiAbsPartIdx ); if( uiIntraDirChroma == DM_CHROMA_IDX ) { m_pcBinIf->encodeBin( 0, m_cCUChromaPredSCModel.get( 0, 0, 0 ) ); } else { m_pcBinIf->encodeBin( 1, m_cCUChromaPredSCModel.get( 0, 0, 0 ) ); UInt uiAllowedChromaDir[ NUM_CHROMA_MODE ]; pcCU->getAllowedChromaDir( uiAbsPartIdx, uiAllowedChromaDir ); for( Int i = 0; i < NUM_CHROMA_MODE - 1; i++ ) { if( uiIntraDirChroma == uiAllowedChromaDir[i] ) { uiIntraDirChroma = i; break; } } m_pcBinIf->encodeBinsEP( uiIntraDirChroma, 2 ); } return; } Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) { const UInt uiInterDir = pcCU->getInterDir( uiAbsPartIdx ) - 1; const UInt uiCtx = pcCU->getCtxInterDir( uiAbsPartIdx ); ContextModel *pCtx = m_cCUInterDirSCModel.get( 0 ); if (pcCU->getPartitionSize(uiAbsPartIdx) == SIZE_2Nx2N || pcCU->getHeight(uiAbsPartIdx) != 8 ) { m_pcBinIf->encodeBin( uiInterDir == 2 ? 1 : 0, *( pCtx + uiCtx ) ); } if (uiInterDir < 2) { m_pcBinIf->encodeBin( uiInterDir, *( pCtx + 4 ) ); } return; } Void TEncSbac::codeRefFrmIdx( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { Int iRefFrame = pcCU->getCUMvField( eRefList )->getRefIdx( uiAbsPartIdx ); ContextModel *pCtx = m_cCURefPicSCModel.get( 0 ); m_pcBinIf->encodeBin( ( iRefFrame == 0 ? 0 : 1 ), *pCtx ); if( iRefFrame > 0 ) { UInt uiRefNum = pcCU->getSlice()->getNumRefIdx( eRefList ) - 2; pCtx++; iRefFrame--; for( UInt ui = 0; ui < uiRefNum; ++ui ) { const UInt uiSymbol = ui == iRefFrame ? 0 : 1; if( ui == 0 ) { m_pcBinIf->encodeBin( uiSymbol, *pCtx ); } else { m_pcBinIf->encodeBinEP( uiSymbol ); } if( uiSymbol == 0 ) { break; } } } return; } Void TEncSbac::codeMvd( TComDataCU* pcCU, UInt uiAbsPartIdx, RefPicList eRefList ) { if(pcCU->getSlice()->getMvdL1ZeroFlag() && eRefList == REF_PIC_LIST_1 && pcCU->getInterDir(uiAbsPartIdx)==3) { return; } const TComCUMvField* pcCUMvField = pcCU->getCUMvField( eRefList ); const Int iHor = pcCUMvField->getMvd( uiAbsPartIdx ).getHor(); const Int iVer = pcCUMvField->getMvd( uiAbsPartIdx ).getVer(); ContextModel* pCtx = m_cCUMvdSCModel.get( 0 ); m_pcBinIf->encodeBin( iHor != 0 ? 1 : 0, *pCtx ); m_pcBinIf->encodeBin( iVer != 0 ? 1 : 0, *pCtx ); const Bool bHorAbsGr0 = iHor != 0; const Bool bVerAbsGr0 = iVer != 0; const UInt uiHorAbs = 0 > iHor ? -iHor : iHor; const UInt uiVerAbs = 0 > iVer ? -iVer : iVer; pCtx++; if( bHorAbsGr0 ) { m_pcBinIf->encodeBin( uiHorAbs > 1 ? 1 : 0, *pCtx ); } if( bVerAbsGr0 ) { m_pcBinIf->encodeBin( uiVerAbs > 1 ? 1 : 0, *pCtx ); } if( bHorAbsGr0 ) { if( uiHorAbs > 1 ) { xWriteEpExGolomb( uiHorAbs-2, 1 ); } m_pcBinIf->encodeBinEP( 0 > iHor ? 1 : 0 ); } if( bVerAbsGr0 ) { if( uiVerAbs > 1 ) { xWriteEpExGolomb( uiVerAbs-2, 1 ); } m_pcBinIf->encodeBinEP( 0 > iVer ? 1 : 0 ); } return; } Void TEncSbac::codeCrossComponentPrediction( TComTU &rTu, ComponentID compID ) { TComDataCU *pcCU = rTu.getCU(); if( isLuma(compID) || !pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() ) { return; } const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); if (!pcCU->isIntra(uiAbsPartIdx) || (pcCU->getIntraDir( CHANNEL_TYPE_CHROMA, uiAbsPartIdx ) == DM_CHROMA_IDX)) { DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T("\tparseCrossComponentPrediction()") DTRACE_CABAC_T( "\tAddr=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( uiAbsPartIdx ) Int alpha = pcCU->getCrossComponentPredictionAlpha( uiAbsPartIdx, compID ); ContextModel *pCtx = m_cCrossComponentPredictionSCModel.get(0, 0) + ((compID == COMPONENT_Cr) ? (NUM_CROSS_COMPONENT_PREDICTION_CTX >> 1) : 0); m_pcBinIf->encodeBin(((alpha != 0) ? 1 : 0), pCtx[0]); if (alpha != 0) { static const Int log2AbsAlphaMinus1Table[8] = { 0, 1, 1, 2, 2, 2, 3, 3 }; assert(abs(alpha) <= 8); if (abs(alpha)>1) { m_pcBinIf->encodeBin(1, pCtx[1]); xWriteUnaryMaxSymbol( log2AbsAlphaMinus1Table[abs(alpha) - 1] - 1, (pCtx + 2), 1, 2 ); } else { m_pcBinIf->encodeBin(0, pCtx[1]); } m_pcBinIf->encodeBin( ((alpha < 0) ? 1 : 0), pCtx[4] ); } DTRACE_CABAC_T( "\tAlpha=" ) DTRACE_CABAC_V( pcCU->getCrossComponentPredictionAlpha( uiAbsPartIdx, compID ) ) DTRACE_CABAC_T( "\n" ) } } Void TEncSbac::codeDeltaQP( TComDataCU* pcCU, UInt uiAbsPartIdx ) { Int iDQp = pcCU->getQP( uiAbsPartIdx ) - pcCU->getRefQP( uiAbsPartIdx ); Int qpBdOffsetY = pcCU->getSlice()->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA); iDQp = (iDQp + 78 + qpBdOffsetY + (qpBdOffsetY/2)) % (52 + qpBdOffsetY) - 26 - (qpBdOffsetY/2); UInt uiAbsDQp = (UInt)((iDQp > 0)? iDQp : (-iDQp)); UInt TUValue = min((Int)uiAbsDQp, CU_DQP_TU_CMAX); xWriteUnaryMaxSymbol( TUValue, &m_cCUDeltaQpSCModel.get( 0, 0, 0 ), 1, CU_DQP_TU_CMAX); if( uiAbsDQp >= CU_DQP_TU_CMAX ) { xWriteEpExGolomb( uiAbsDQp - CU_DQP_TU_CMAX, CU_DQP_EG_k ); } if ( uiAbsDQp > 0) { UInt uiSign = (iDQp > 0 ? 0 : 1); m_pcBinIf->encodeBinEP(uiSign); } return; } /** code chroma qp adjustment, converting from the internal table representation * \returns Void */ Void TEncSbac::codeChromaQpAdjustment( TComDataCU* cu, UInt absPartIdx ) { Int internalIdc = cu->getChromaQpAdj( absPartIdx ); Int chromaQpOffsetListLen = cu->getSlice()->getPPS()->getPpsRangeExtension().getChromaQpOffsetListLen(); /* internal_idc == 0 => flag = 0 * internal_idc > 1 => code idc value (if table size warrents) */ m_pcBinIf->encodeBin( internalIdc > 0, m_ChromaQpAdjFlagSCModel.get( 0, 0, 0 ) ); if (internalIdc > 0 && chromaQpOffsetListLen > 1) { xWriteUnaryMaxSymbol( internalIdc - 1, &m_ChromaQpAdjIdcSCModel.get( 0, 0, 0 ), 0, chromaQpOffsetListLen - 1 ); } } Void TEncSbac::codeQtCbf( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) { TComDataCU* pcCU = rTu.getCU(); const UInt absPartIdx = rTu.GetAbsPartIdxTU(compID); const UInt TUDepth = rTu.GetTransformDepthRel(); UInt uiCtx = pcCU->getCtxQtCbf( rTu, toChannelType(compID) ); const UInt contextSet = toChannelType(compID); const UInt width = rTu.getRect(compID).width; const UInt height = rTu.getRect(compID).height; const Bool canQuadSplit = (width >= (MIN_TU_SIZE * 2)) && (height >= (MIN_TU_SIZE * 2)); // Since the CBF for chroma is coded at the highest level possible, if sub-TUs are // to be coded for a 4x8 chroma TU, their CBFs must be coded at the highest 4x8 level // (i.e. where luma TUs are 8x8 rather than 4x4) // ___ ___ // | | | <- 4 x (8x8 luma + 4x8 4:2:2 chroma) // |___|___| each quadrant has its own chroma CBF // | | | _ _ _ _ // |___|___| | // <--16---> V // _ _ // |_|_| <- 4 x 4x4 luma + 1 x 4x8 4:2:2 chroma // |_|_| no chroma CBF is coded - instead the parent CBF is inherited // <-8-> if sub-TUs are present, their CBFs had to be coded at the parent level const UInt lowestTUDepth = TUDepth + ((!lowestLevel && !canQuadSplit) ? 1 : 0); //unsplittable TUs inherit their parent's CBF if ((width != height) && (lowestLevel || !canQuadSplit)) //if sub-TUs are present { const UInt subTUDepth = lowestTUDepth + 1; //if this is the lowest level of the TU-tree, the sub-TUs are directly below. Otherwise, this must be the level above the lowest level (as specified above) const UInt partIdxesPerSubTU = rTu.GetAbsPartIdxNumParts(compID) >> 1; for (UInt subTU = 0; subTU < 2; subTU++) { const UInt subTUAbsPartIdx = absPartIdx + (subTU * partIdxesPerSubTU); const UInt uiCbf = pcCU->getCbf(subTUAbsPartIdx, compID, subTUDepth); m_pcBinIf->encodeBin(uiCbf, m_cCUQtCbfSCModel.get(0, contextSet, uiCtx)); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtCbf()" ) DTRACE_CABAC_T( "\tsub-TU=" ) DTRACE_CABAC_V( subTU ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiCbf ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( subTUAbsPartIdx ) DTRACE_CABAC_T( "\n" ) } } else { const UInt uiCbf = pcCU->getCbf( absPartIdx, compID, lowestTUDepth ); m_pcBinIf->encodeBin( uiCbf , m_cCUQtCbfSCModel.get( 0, contextSet, uiCtx ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtCbf()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiCbf ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( rTu.GetAbsPartIdxTU(compID) ) DTRACE_CABAC_T( "\n" ) } } Void TEncSbac::codeTransformSkipFlags (TComTU &rTu, ComponentID component ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); if (pcCU->getCUTransquantBypass(uiAbsPartIdx)) { return; } if (!TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(component), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize())) { return; } UInt useTransformSkip = pcCU->getTransformSkip( uiAbsPartIdx,component); m_pcBinIf->encodeBin( useTransformSkip, m_cTransformSkipSCModel.get( 0, toChannelType(component), 0 ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T("\tparseTransformSkip()"); DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( useTransformSkip ) DTRACE_CABAC_T( "\tAddr=" ) DTRACE_CABAC_V( pcCU->getCtuRsAddr() ) DTRACE_CABAC_T( "\tetype=" ) DTRACE_CABAC_V( component ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( rTu.GetAbsPartIdxTU() ) DTRACE_CABAC_T( "\n" ) } /** Code I_PCM information. * \param pcCU pointer to CU * \param uiAbsPartIdx CU index * \returns Void */ Void TEncSbac::codeIPCMInfo( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiIPCM = (pcCU->getIPCMFlag(uiAbsPartIdx) == true)? 1 : 0; Bool writePCMSampleFlag = pcCU->getIPCMFlag(uiAbsPartIdx); m_pcBinIf->encodeBinTrm (uiIPCM); if (writePCMSampleFlag) { m_pcBinIf->encodePCMAlignBits(); const UInt minCoeffSizeY = pcCU->getPic()->getMinCUWidth() * pcCU->getPic()->getMinCUHeight(); const UInt offsetY = minCoeffSizeY * uiAbsPartIdx; for (UInt ch=0; ch < pcCU->getPic()->getNumberValidComponents(); ch++) { const ComponentID compID = ComponentID(ch); const UInt offset = offsetY >> (pcCU->getPic()->getComponentScaleX(compID) + pcCU->getPic()->getComponentScaleY(compID)); Pel * pPCMSample = pcCU->getPCMSample(compID) + offset; const UInt width = pcCU->getWidth (uiAbsPartIdx) >> pcCU->getPic()->getComponentScaleX(compID); const UInt height = pcCU->getHeight(uiAbsPartIdx) >> pcCU->getPic()->getComponentScaleY(compID); const UInt sampleBits = pcCU->getSlice()->getSPS()->getPCMBitDepth(toChannelType(compID)); for (UInt y=0; yxWritePCMCode(sample, sampleBits); } pPCMSample += width; } } m_pcBinIf->resetBac(); } } Void TEncSbac::codeQtRootCbf( TComDataCU* pcCU, UInt uiAbsPartIdx ) { UInt uiCbf = pcCU->getQtRootCbf( uiAbsPartIdx ); UInt uiCtx = 0; m_pcBinIf->encodeBin( uiCbf , m_cCUQtRootCbfSCModel.get( 0, 0, uiCtx ) ); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseQtRootCbf()" ) DTRACE_CABAC_T( "\tsymbol=" ) DTRACE_CABAC_V( uiCbf ) DTRACE_CABAC_T( "\tctx=" ) DTRACE_CABAC_V( uiCtx ) DTRACE_CABAC_T( "\tuiAbsPartIdx=" ) DTRACE_CABAC_V( uiAbsPartIdx ) DTRACE_CABAC_T( "\n" ) } Void TEncSbac::codeQtCbfZero( TComTU & rTu, const ChannelType chType ) { // this function is only used to estimate the bits when cbf is 0 // and will never be called when writing the bistream. do not need to write log UInt uiCbf = 0; UInt uiCtx = rTu.getCU()->getCtxQtCbf( rTu, chType ); m_pcBinIf->encodeBin( uiCbf , m_cCUQtCbfSCModel.get( 0, chType, uiCtx ) ); } Void TEncSbac::codeQtRootCbfZero( ) { // this function is only used to estimate the bits when cbf is 0 // and will never be called when writing the bistream. do not need to write log UInt uiCbf = 0; UInt uiCtx = 0; m_pcBinIf->encodeBin( uiCbf , m_cCUQtRootCbfSCModel.get( 0, 0, uiCtx ) ); } /** Encode (X,Y) position of the last significant coefficient * \param uiPosX X component of last coefficient * \param uiPosY Y component of last coefficient * \param width Block width * \param height Block height * \param component chroma component ID * \param uiScanIdx scan type (zig-zag, hor, ver) * This method encodes the X and Y component within a block of the last significant coefficient. */ Void TEncSbac::codeLastSignificantXY( UInt uiPosX, UInt uiPosY, Int width, Int height, ComponentID component, UInt uiScanIdx ) { // swap if( uiScanIdx == SCAN_VER ) { swap( uiPosX, uiPosY ); swap( width, height ); } UInt uiCtxLast; UInt uiGroupIdxX = g_uiGroupIdx[ uiPosX ]; UInt uiGroupIdxY = g_uiGroupIdx[ uiPosY ]; ContextModel *pCtxX = m_cCuCtxLastX.get( 0, toChannelType(component) ); ContextModel *pCtxY = m_cCuCtxLastY.get( 0, toChannelType(component) ); Int blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY; getLastSignificantContextParameters(component, width, height, blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY); //------------------ // posX for( uiCtxLast = 0; uiCtxLast < uiGroupIdxX; uiCtxLast++ ) { m_pcBinIf->encodeBin( 1, *( pCtxX + blkSizeOffsetX + (uiCtxLast >>shiftX) ) ); } if( uiGroupIdxX < g_uiGroupIdx[ width - 1 ]) { m_pcBinIf->encodeBin( 0, *( pCtxX + blkSizeOffsetX + (uiCtxLast >>shiftX) ) ); } // posY for( uiCtxLast = 0; uiCtxLast < uiGroupIdxY; uiCtxLast++ ) { m_pcBinIf->encodeBin( 1, *( pCtxY + blkSizeOffsetY + (uiCtxLast >>shiftY) ) ); } if( uiGroupIdxY < g_uiGroupIdx[ height - 1 ]) { m_pcBinIf->encodeBin( 0, *( pCtxY + blkSizeOffsetY + (uiCtxLast >>shiftY) ) ); } // EP-coded part if ( uiGroupIdxX > 3 ) { UInt uiCount = ( uiGroupIdxX - 2 ) >> 1; uiPosX = uiPosX - g_uiMinInGroup[ uiGroupIdxX ]; for (Int i = uiCount - 1 ; i >= 0; i-- ) { m_pcBinIf->encodeBinEP( ( uiPosX >> i ) & 1 ); } } if ( uiGroupIdxY > 3 ) { UInt uiCount = ( uiGroupIdxY - 2 ) >> 1; uiPosY = uiPosY - g_uiMinInGroup[ uiGroupIdxY ]; for ( Int i = uiCount - 1 ; i >= 0; i-- ) { m_pcBinIf->encodeBinEP( ( uiPosY >> i ) & 1 ); } } } Void TEncSbac::codeCoeffNxN( TComTU &rTu, TCoeff* pcCoef, const ComponentID compID ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(compID); const TComRectangle &tuRect=rTu.getRect(compID); const UInt uiWidth=tuRect.width; const UInt uiHeight=tuRect.height; const TComSPS &sps=*(pcCU->getSlice()->getSPS()); DTRACE_CABAC_VL( g_nSymbolCounter++ ) DTRACE_CABAC_T( "\tparseCoeffNxN()\teType=" ) DTRACE_CABAC_V( compID ) DTRACE_CABAC_T( "\twidth=" ) DTRACE_CABAC_V( uiWidth ) DTRACE_CABAC_T( "\theight=" ) DTRACE_CABAC_V( uiHeight ) DTRACE_CABAC_T( "\tdepth=" ) // DTRACE_CABAC_V( rTu.GetTransformDepthTotalAdj(compID) ) DTRACE_CABAC_V( rTu.GetTransformDepthTotal() ) DTRACE_CABAC_T( "\tabspartidx=" ) DTRACE_CABAC_V( uiAbsPartIdx ) DTRACE_CABAC_T( "\ttoCU-X=" ) DTRACE_CABAC_V( pcCU->getCUPelX() ) DTRACE_CABAC_T( "\ttoCU-Y=" ) DTRACE_CABAC_V( pcCU->getCUPelY() ) DTRACE_CABAC_T( "\tCU-addr=" ) DTRACE_CABAC_V( pcCU->getCtuRsAddr() ) DTRACE_CABAC_T( "\tinCU-X=" ) // DTRACE_CABAC_V( g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ] ) DTRACE_CABAC_V( g_auiRasterToPelX[ g_auiZscanToRaster[rTu.GetAbsPartIdxTU(compID)] ] ) DTRACE_CABAC_T( "\tinCU-Y=" ) // DTRACE_CABAC_V( g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ] ) DTRACE_CABAC_V( g_auiRasterToPelY[ g_auiZscanToRaster[rTu.GetAbsPartIdxTU(compID)] ] ) DTRACE_CABAC_T( "\tpredmode=" ) DTRACE_CABAC_V( pcCU->getPredictionMode( uiAbsPartIdx ) ) DTRACE_CABAC_T( "\n" ) //-------------------------------------------------------------------------------------------------- if( uiWidth > sps.getMaxTrSize() ) { std::cerr << "ERROR: codeCoeffNxN was passed a TU with dimensions larger than the maximum allowed size" << std::endl; assert(false); exit(1); } // compute number of significant coefficients UInt uiNumSig = TEncEntropy::countNonZeroCoeffs(pcCoef, uiWidth * uiHeight); if ( uiNumSig == 0 ) { std::cerr << "ERROR: codeCoeffNxN called for empty TU!" << std::endl; assert(false); exit(1); } //-------------------------------------------------------------------------------------------------- //set parameters const ChannelType chType = toChannelType(compID); const UInt uiLog2BlockWidth = g_aucConvertToBit[ uiWidth ] + 2; const UInt uiLog2BlockHeight = g_aucConvertToBit[ uiHeight ] + 2; const ChannelType channelType = toChannelType(compID); const Bool extendedPrecision = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag(); const Bool alignCABACBeforeBypass = sps.getSpsRangeExtension().getCabacBypassAlignmentEnabledFlag(); const Int maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(channelType); Bool beValid; { Int uiIntraMode = -1; const Bool bIsLuma = isLuma(compID); Int isIntra = pcCU->isIntra(uiAbsPartIdx) ? 1 : 0; if ( isIntra ) { uiIntraMode = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx ); const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize())); uiIntraMode = (uiIntraMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, rTu.GetChromaFormat(), partsPerMinCU)) : uiIntraMode; uiIntraMode = ((rTu.GetChromaFormat() == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiIntraMode] : uiIntraMode; } Int transformSkip = pcCU->getTransformSkip( uiAbsPartIdx,compID) ? 1 : 0; Bool rdpcm_lossy = ( transformSkip && isIntra && ( (uiIntraMode == HOR_IDX) || (uiIntraMode == VER_IDX) ) ) && pcCU->isRDPCMEnabled(uiAbsPartIdx); if ( (pcCU->getCUTransquantBypass(uiAbsPartIdx)) || rdpcm_lossy ) { beValid = false; if ( (!pcCU->isIntra(uiAbsPartIdx)) && pcCU->isRDPCMEnabled(uiAbsPartIdx)) { codeExplicitRdpcmMode( rTu, compID); } } else { beValid = pcCU->getSlice()->getPPS()->getSignDataHidingEnabledFlag(); } } //-------------------------------------------------------------------------------------------------- if(pcCU->getSlice()->getPPS()->getUseTransformSkip()) { codeTransformSkipFlags(rTu, compID); if(pcCU->getTransformSkip(uiAbsPartIdx, compID) && !pcCU->isIntra(uiAbsPartIdx) && pcCU->isRDPCMEnabled(uiAbsPartIdx)) { // This TU has coefficients and is transform skipped. Check whether is inter coded and if yes encode the explicit RDPCM mode codeExplicitRdpcmMode( rTu, compID); if(pcCU->getExplicitRdpcmMode(compID, uiAbsPartIdx) != RDPCM_OFF) { // Sign data hiding is avoided for horizontal and vertical explicit RDPCM modes beValid = false; } } } //-------------------------------------------------------------------------------------------------- const Bool bUseGolombRiceParameterAdaptation = sps.getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag(); UInt ¤tGolombRiceStatistic = m_golombRiceAdaptationStatistics[rTu.getGolombRiceStatisticsIndex(compID)]; //select scans TUEntropyCodingParameters codingParameters; getTUEntropyCodingParameters(codingParameters, rTu, compID); //----- encode significance map ----- // Find position of last coefficient Int scanPosLast = -1; Int posLast; UInt uiSigCoeffGroupFlag[ MLS_GRP_NUM ]; memset( uiSigCoeffGroupFlag, 0, sizeof(UInt) * MLS_GRP_NUM ); do { posLast = codingParameters.scan[ ++scanPosLast ]; if( pcCoef[ posLast ] != 0 ) { // get L1 sig map UInt uiPosY = posLast >> uiLog2BlockWidth; UInt uiPosX = posLast - ( uiPosY << uiLog2BlockWidth ); UInt uiBlkIdx = (codingParameters.widthInGroups * (uiPosY >> MLS_CG_LOG2_HEIGHT)) + (uiPosX >> MLS_CG_LOG2_WIDTH); uiSigCoeffGroupFlag[ uiBlkIdx ] = 1; uiNumSig--; } } while ( uiNumSig > 0 ); // Code position of last coefficient Int posLastY = posLast >> uiLog2BlockWidth; Int posLastX = posLast - ( posLastY << uiLog2BlockWidth ); codeLastSignificantXY(posLastX, posLastY, uiWidth, uiHeight, compID, codingParameters.scanType); //===== code significance flag ===== ContextModel * const baseCoeffGroupCtx = m_cCUSigCoeffGroupSCModel.get( 0, chType ); ContextModel * const baseCtx = m_cCUSigSCModel.get( 0, 0 ) + getSignificanceMapContextOffset(compID); const Int iLastScanSet = scanPosLast >> MLS_CG_SIZE; UInt c1 = 1; UInt uiGoRiceParam = 0; Int iScanPosSig = scanPosLast; for( Int iSubSet = iLastScanSet; iSubSet >= 0; iSubSet-- ) { Int numNonZero = 0; Int iSubPos = iSubSet << MLS_CG_SIZE; uiGoRiceParam = currentGolombRiceStatistic / RExt__GOLOMB_RICE_INCREMENT_DIVISOR; Bool updateGolombRiceStatistics = bUseGolombRiceParameterAdaptation; //leave the statistics at 0 when not using the adaptation system UInt coeffSigns = 0; Int absCoeff[1 << MLS_CG_SIZE]; Int lastNZPosInCG = -1; Int firstNZPosInCG = 1 << MLS_CG_SIZE; Bool escapeDataPresentInGroup = false; if( iScanPosSig == scanPosLast ) { absCoeff[ 0 ] = Int(abs( pcCoef[ posLast ] )); coeffSigns = ( pcCoef[ posLast ] < 0 ); numNonZero = 1; lastNZPosInCG = iScanPosSig; firstNZPosInCG = iScanPosSig; iScanPosSig--; } // encode significant_coeffgroup_flag Int iCGBlkPos = codingParameters.scanCG[ iSubSet ]; Int iCGPosY = iCGBlkPos / codingParameters.widthInGroups; Int iCGPosX = iCGBlkPos - (iCGPosY * codingParameters.widthInGroups); if( iSubSet == iLastScanSet || iSubSet == 0) { uiSigCoeffGroupFlag[ iCGBlkPos ] = 1; } else { UInt uiSigCoeffGroup = (uiSigCoeffGroupFlag[ iCGBlkPos ] != 0); UInt uiCtxSig = TComTrQuant::getSigCoeffGroupCtxInc( uiSigCoeffGroupFlag, iCGPosX, iCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups ); m_pcBinIf->encodeBin( uiSigCoeffGroup, baseCoeffGroupCtx[ uiCtxSig ] ); } // encode significant_coeff_flag if( uiSigCoeffGroupFlag[ iCGBlkPos ] ) { const Int patternSigCtx = TComTrQuant::calcPatternSigCtx(uiSigCoeffGroupFlag, iCGPosX, iCGPosY, codingParameters.widthInGroups, codingParameters.heightInGroups); UInt uiBlkPos, uiSig, uiCtxSig; for( ; iScanPosSig >= iSubPos; iScanPosSig-- ) { uiBlkPos = codingParameters.scan[ iScanPosSig ]; uiSig = (pcCoef[ uiBlkPos ] != 0); if( iScanPosSig > iSubPos || iSubSet == 0 || numNonZero ) { uiCtxSig = TComTrQuant::getSigCtxInc( patternSigCtx, codingParameters, iScanPosSig, uiLog2BlockWidth, uiLog2BlockHeight, chType ); m_pcBinIf->encodeBin( uiSig, baseCtx[ uiCtxSig ] ); } if( uiSig ) { absCoeff[ numNonZero ] = Int(abs( pcCoef[ uiBlkPos ] )); coeffSigns = 2 * coeffSigns + ( pcCoef[ uiBlkPos ] < 0 ); numNonZero++; if( lastNZPosInCG == -1 ) { lastNZPosInCG = iScanPosSig; } firstNZPosInCG = iScanPosSig; } } } else { iScanPosSig = iSubPos - 1; } if( numNonZero > 0 ) { Bool signHidden = ( lastNZPosInCG - firstNZPosInCG >= SBH_THRESHOLD ); const UInt uiCtxSet = getContextSetIndex(compID, iSubSet, (c1 == 0)); c1 = 1; ContextModel *baseCtxMod = m_cCUOneSCModel.get( 0, 0 ) + (NUM_ONE_FLAG_CTX_PER_SET * uiCtxSet); Int numC1Flag = min(numNonZero, C1FLAG_NUMBER); Int firstC2FlagIdx = -1; for( Int idx = 0; idx < numC1Flag; idx++ ) { UInt uiSymbol = absCoeff[ idx ] > 1; m_pcBinIf->encodeBin( uiSymbol, baseCtxMod[c1] ); if( uiSymbol ) { c1 = 0; if (firstC2FlagIdx == -1) { firstC2FlagIdx = idx; } else //if a greater-than-one has been encountered already this group { escapeDataPresentInGroup = true; } } else if( (c1 < 3) && (c1 > 0) ) { c1++; } } if (c1 == 0) { baseCtxMod = m_cCUAbsSCModel.get( 0, 0 ) + (NUM_ABS_FLAG_CTX_PER_SET * uiCtxSet); if ( firstC2FlagIdx != -1) { UInt symbol = absCoeff[ firstC2FlagIdx ] > 2; m_pcBinIf->encodeBin( symbol, baseCtxMod[0] ); if (symbol != 0) { escapeDataPresentInGroup = true; } } } escapeDataPresentInGroup = escapeDataPresentInGroup || (numNonZero > C1FLAG_NUMBER); if (escapeDataPresentInGroup && alignCABACBeforeBypass) { m_pcBinIf->align(); } if( beValid && signHidden ) { m_pcBinIf->encodeBinsEP( (coeffSigns >> 1), numNonZero-1 ); } else { m_pcBinIf->encodeBinsEP( coeffSigns, numNonZero ); } Int iFirstCoeff2 = 1; if (escapeDataPresentInGroup) { for ( Int idx = 0; idx < numNonZero; idx++ ) { UInt baseLevel = (idx < C1FLAG_NUMBER)? (2 + iFirstCoeff2 ) : 1; if( absCoeff[ idx ] >= baseLevel) { const UInt escapeCodeValue = absCoeff[idx] - baseLevel; xWriteCoefRemainExGolomb( escapeCodeValue, uiGoRiceParam, extendedPrecision, maxLog2TrDynamicRange ); if (absCoeff[idx] > (3 << uiGoRiceParam)) { uiGoRiceParam = bUseGolombRiceParameterAdaptation ? (uiGoRiceParam + 1) : (std::min((uiGoRiceParam + 1), 4)); } if (updateGolombRiceStatistics) { const UInt initialGolombRiceParameter = currentGolombRiceStatistic / RExt__GOLOMB_RICE_INCREMENT_DIVISOR; if (escapeCodeValue >= (3 << initialGolombRiceParameter)) { currentGolombRiceStatistic++; } else if (((escapeCodeValue * 2) < (1 << initialGolombRiceParameter)) && (currentGolombRiceStatistic > 0)) { currentGolombRiceStatistic--; } updateGolombRiceStatistics = false; } } if(absCoeff[ idx ] >= 2) { iFirstCoeff2 = 0; } } } } } #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST printSBACCoeffData(posLastX, posLastY, uiWidth, uiHeight, compID, uiAbsPartIdx, codingParameters.scanType, pcCoef, pcCU->getSlice()->getFinalized()); #endif return; } /** code SAO offset sign * \param code sign value */ Void TEncSbac::codeSAOSign( UInt code ) { m_pcBinIf->encodeBinEP( code ); } Void TEncSbac::codeSaoMaxUvlc ( UInt code, UInt maxSymbol ) { if (maxSymbol == 0) { return; } Int i; Bool bCodeLast = ( maxSymbol > code ); if ( code == 0 ) { m_pcBinIf->encodeBinEP( 0 ); } else { m_pcBinIf->encodeBinEP( 1 ); for ( i=0; iencodeBinEP( 1 ); } if( bCodeLast ) { m_pcBinIf->encodeBinEP( 0 ); } } } /** Code SAO EO class or BO band position */ Void TEncSbac::codeSaoUflc ( UInt uiLength, UInt uiCode ) { m_pcBinIf->encodeBinsEP ( uiCode, uiLength ); } /** Code SAO merge flags */ Void TEncSbac::codeSaoMerge ( UInt uiCode ) { m_pcBinIf->encodeBin(((uiCode == 0) ? 0 : 1), m_cSaoMergeSCModel.get( 0, 0, 0 )); } /** Code SAO type index */ Void TEncSbac::codeSaoTypeIdx ( UInt uiCode) { if (uiCode == 0) { m_pcBinIf->encodeBin( 0, m_cSaoTypeIdxSCModel.get( 0, 0, 0 ) ); } else { m_pcBinIf->encodeBin( 1, m_cSaoTypeIdxSCModel.get( 0, 0, 0 ) ); m_pcBinIf->encodeBinEP( uiCode == 1 ? 0 : 1 ); } } Void TEncSbac::codeSAOOffsetParam(ComponentID compIdx, SAOOffset& ctbParam, Bool sliceEnabled, const Int channelBitDepth) { UInt uiSymbol; if(!sliceEnabled) { assert(ctbParam.modeIdc == SAO_MODE_OFF); return; } const Bool bIsFirstCompOfChType = (getFirstComponentOfChannel(toChannelType(compIdx)) == compIdx); //type if(bIsFirstCompOfChType) { //sao_type_idx_luma or sao_type_idx_chroma if(ctbParam.modeIdc == SAO_MODE_OFF) { uiSymbol =0; } else if(ctbParam.typeIdc == SAO_TYPE_BO) //BO { uiSymbol = 1; } else { assert(ctbParam.typeIdc < SAO_TYPE_START_BO); //EO uiSymbol = 2; } codeSaoTypeIdx(uiSymbol); } if(ctbParam.modeIdc == SAO_MODE_NEW) { Int numClasses = (ctbParam.typeIdc == SAO_TYPE_BO)?4:NUM_SAO_EO_CLASSES; Int offset[4]; Int k=0; for(Int i=0; i< numClasses; i++) { if(ctbParam.typeIdc != SAO_TYPE_BO && i == SAO_CLASS_EO_PLAIN) { continue; } Int classIdx = (ctbParam.typeIdc == SAO_TYPE_BO)?( (ctbParam.typeAuxInfo+i)% NUM_SAO_BO_CLASSES ):i; offset[k] = ctbParam.offset[classIdx]; k++; } const Int maxOffsetQVal = TComSampleAdaptiveOffset::getMaxOffsetQVal(channelBitDepth); for(Int i=0; i< 4; i++) { codeSaoMaxUvlc((offset[i]<0)?(-offset[i]):(offset[i]), maxOffsetQVal ); //sao_offset_abs } if(ctbParam.typeIdc == SAO_TYPE_BO) { for(Int i=0; i< 4; i++) { if(offset[i] != 0) { codeSAOSign((offset[i]< 0)?1:0); } } codeSaoUflc(NUM_SAO_BO_CLASSES_LOG2, ctbParam.typeAuxInfo ); //sao_band_position } else //EO { if(bIsFirstCompOfChType) { assert(ctbParam.typeIdc - SAO_TYPE_START_EO >=0); codeSaoUflc(NUM_SAO_EO_TYPES_LOG2, ctbParam.typeIdc - SAO_TYPE_START_EO ); //sao_eo_class_luma or sao_eo_class_chroma } } } } Void TEncSbac::codeSAOBlkParam(SAOBlkParam& saoBlkParam, const BitDepths &bitDepths , Bool* sliceEnabled , Bool leftMergeAvail , Bool aboveMergeAvail , Bool onlyEstMergeInfo // = false ) { Bool isLeftMerge = false; Bool isAboveMerge= false; if(leftMergeAvail) { isLeftMerge = ((saoBlkParam[COMPONENT_Y].modeIdc == SAO_MODE_MERGE) && (saoBlkParam[COMPONENT_Y].typeIdc == SAO_MERGE_LEFT)); codeSaoMerge( isLeftMerge?1:0 ); //sao_merge_left_flag } if( aboveMergeAvail && !isLeftMerge) { isAboveMerge = ((saoBlkParam[COMPONENT_Y].modeIdc == SAO_MODE_MERGE) && (saoBlkParam[COMPONENT_Y].typeIdc == SAO_MERGE_ABOVE)); codeSaoMerge( isAboveMerge?1:0 ); //sao_merge_left_flag } if(onlyEstMergeInfo) { return; //only for RDO } if(!isLeftMerge && !isAboveMerge) //not merge mode { for(Int compIdx=0; compIdx < MAX_NUM_COMPONENT; compIdx++) { codeSAOOffsetParam(ComponentID(compIdx), saoBlkParam[compIdx], sliceEnabled[compIdx], bitDepths.recon[toChannelType(ComponentID(compIdx))]); } } } /*! **************************************************************************** * \brief * estimate bit cost for CBP, significant map and significant coefficients **************************************************************************** */ Void TEncSbac::estBit( estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType, COEFF_SCAN_TYPE scanType ) { estCBFBit( pcEstBitsSbac ); estSignificantCoeffGroupMapBit( pcEstBitsSbac, chType ); // encode significance map estSignificantMapBit( pcEstBitsSbac, width, height, chType ); // encode last significant position estLastSignificantPositionBit( pcEstBitsSbac, width, height, chType, scanType ); // encode significant coefficients estSignificantCoefficientsBit( pcEstBitsSbac, chType ); memcpy(pcEstBitsSbac->golombRiceAdaptationStatistics, m_golombRiceAdaptationStatistics, (sizeof(UInt) * RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS)); } /*! **************************************************************************** * \brief * estimate bit cost for each CBP bit **************************************************************************** */ Void TEncSbac::estCBFBit( estBitsSbacStruct* pcEstBitsSbac ) { ContextModel *pCtx = m_cCUQtCbfSCModel.get( 0 ); for( UInt uiCtxInc = 0; uiCtxInc < (NUM_QT_CBF_CTX_SETS * NUM_QT_CBF_CTX_PER_SET); uiCtxInc++ ) { pcEstBitsSbac->blockCbpBits[ uiCtxInc ][ 0 ] = pCtx[ uiCtxInc ].getEntropyBits( 0 ); pcEstBitsSbac->blockCbpBits[ uiCtxInc ][ 1 ] = pCtx[ uiCtxInc ].getEntropyBits( 1 ); } pCtx = m_cCUQtRootCbfSCModel.get( 0 ); for( UInt uiCtxInc = 0; uiCtxInc < 4; uiCtxInc++ ) { pcEstBitsSbac->blockRootCbpBits[ uiCtxInc ][ 0 ] = pCtx[ uiCtxInc ].getEntropyBits( 0 ); pcEstBitsSbac->blockRootCbpBits[ uiCtxInc ][ 1 ] = pCtx[ uiCtxInc ].getEntropyBits( 1 ); } } /*! **************************************************************************** * \brief * estimate SAMBAC bit cost for significant coefficient group map **************************************************************************** */ Void TEncSbac::estSignificantCoeffGroupMapBit( estBitsSbacStruct* pcEstBitsSbac, ChannelType chType ) { Int firstCtx = 0, numCtx = NUM_SIG_CG_FLAG_CTX; for ( Int ctxIdx = firstCtx; ctxIdx < firstCtx + numCtx; ctxIdx++ ) { for( UInt uiBin = 0; uiBin < 2; uiBin++ ) { pcEstBitsSbac->significantCoeffGroupBits[ ctxIdx ][ uiBin ] = m_cCUSigCoeffGroupSCModel.get( 0, chType, ctxIdx ).getEntropyBits( uiBin ); } } } /*! **************************************************************************** * \brief * estimate SAMBAC bit cost for significant coefficient map **************************************************************************** */ Void TEncSbac::estSignificantMapBit( estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType ) { //-------------------------------------------------------------------------------------------------- //set up the number of channels and context variables const UInt firstComponent = ((isLuma(chType)) ? (COMPONENT_Y) : (COMPONENT_Cb)); const UInt lastComponent = ((isLuma(chType)) ? (COMPONENT_Y) : (COMPONENT_Cb)); //---------------------------------------------------------- Int firstCtx = MAX_INT; Int numCtx = MAX_INT; if ((width == 4) && (height == 4)) { firstCtx = significanceMapContextSetStart[chType][CONTEXT_TYPE_4x4]; numCtx = significanceMapContextSetSize [chType][CONTEXT_TYPE_4x4]; } else if ((width == 8) && (height == 8)) { firstCtx = significanceMapContextSetStart[chType][CONTEXT_TYPE_8x8]; numCtx = significanceMapContextSetSize [chType][CONTEXT_TYPE_8x8]; } else { firstCtx = significanceMapContextSetStart[chType][CONTEXT_TYPE_NxN]; numCtx = significanceMapContextSetSize [chType][CONTEXT_TYPE_NxN]; } //-------------------------------------------------------------------------------------------------- //fill the data for the significace map for (UInt component = firstComponent; component <= lastComponent; component++) { const UInt contextOffset = getSignificanceMapContextOffset(ComponentID(component)); if (firstCtx > 0) { for( UInt bin = 0; bin < 2; bin++ ) //always get the DC { pcEstBitsSbac->significantBits[ contextOffset ][ bin ] = m_cCUSigSCModel.get( 0, 0, contextOffset ).getEntropyBits( bin ); } } // This could be made optional, but would require this function to have knowledge of whether the // TU is transform-skipped or transquant-bypassed and whether the SPS flag is set for( UInt bin = 0; bin < 2; bin++ ) { const Int ctxIdx = significanceMapContextSetStart[chType][CONTEXT_TYPE_SINGLE]; pcEstBitsSbac->significantBits[ contextOffset + ctxIdx ][ bin ] = m_cCUSigSCModel.get( 0, 0, (contextOffset + ctxIdx) ).getEntropyBits( bin ); } for ( Int ctxIdx = firstCtx; ctxIdx < firstCtx + numCtx; ctxIdx++ ) { for( UInt uiBin = 0; uiBin < 2; uiBin++ ) { pcEstBitsSbac->significantBits[ contextOffset + ctxIdx ][ uiBin ] = m_cCUSigSCModel.get( 0, 0, (contextOffset + ctxIdx) ).getEntropyBits( uiBin ); } } } //-------------------------------------------------------------------------------------------------- } /*! **************************************************************************** * \brief * estimate bit cost of significant coefficient **************************************************************************** */ Void TEncSbac::estLastSignificantPositionBit( estBitsSbacStruct* pcEstBitsSbac, Int width, Int height, ChannelType chType, COEFF_SCAN_TYPE scanType ) { if (scanType == SCAN_VER) { swap(width, height); } //--------------------------------------------------------------------------------------------------. //set up the number of channels const UInt firstComponent = ((isLuma(chType)) ? (COMPONENT_Y) : (COMPONENT_Cb)); const UInt lastComponent = ((isLuma(chType)) ? (COMPONENT_Y) : (COMPONENT_Cb)); //-------------------------------------------------------------------------------------------------- //fill the data for the last-significant-coefficient position for (UInt componentIndex = firstComponent; componentIndex <= lastComponent; componentIndex++) { const ComponentID component = ComponentID(componentIndex); Int iBitsX = 0, iBitsY = 0; Int blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY; getLastSignificantContextParameters(ComponentID(component), width, height, blkSizeOffsetX, blkSizeOffsetY, shiftX, shiftY); Int ctx; const ChannelType channelType = toChannelType(ComponentID(component)); ContextModel *const pCtxX = m_cCuCtxLastX.get( 0, channelType ); ContextModel *const pCtxY = m_cCuCtxLastY.get( 0, channelType ); Int *const lastXBitsArray = pcEstBitsSbac->lastXBits[channelType]; Int *const lastYBitsArray = pcEstBitsSbac->lastYBits[channelType]; //------------------------------------------------ //X-coordinate for (ctx = 0; ctx < g_uiGroupIdx[ width - 1 ]; ctx++) { Int ctxOffset = blkSizeOffsetX + (ctx >>shiftX); lastXBitsArray[ ctx ] = iBitsX + pCtxX[ ctxOffset ].getEntropyBits( 0 ); iBitsX += pCtxX[ ctxOffset ].getEntropyBits( 1 ); } lastXBitsArray[ctx] = iBitsX; //------------------------------------------------ //Y-coordinate for (ctx = 0; ctx < g_uiGroupIdx[ height - 1 ]; ctx++) { Int ctxOffset = blkSizeOffsetY + (ctx >>shiftY); lastYBitsArray[ ctx ] = iBitsY + pCtxY[ ctxOffset ].getEntropyBits( 0 ); iBitsY += pCtxY[ ctxOffset ].getEntropyBits( 1 ); } lastYBitsArray[ctx] = iBitsY; } //end of component loop //-------------------------------------------------------------------------------------------------- } /*! **************************************************************************** * \brief * estimate bit cost of significant coefficient **************************************************************************** */ Void TEncSbac::estSignificantCoefficientsBit( estBitsSbacStruct* pcEstBitsSbac, ChannelType chType ) { ContextModel *ctxOne = m_cCUOneSCModel.get(0, 0); ContextModel *ctxAbs = m_cCUAbsSCModel.get(0, 0); const UInt oneStartIndex = ((isLuma(chType)) ? (0) : (NUM_ONE_FLAG_CTX_LUMA)); const UInt oneStopIndex = ((isLuma(chType)) ? (NUM_ONE_FLAG_CTX_LUMA) : (NUM_ONE_FLAG_CTX)); const UInt absStartIndex = ((isLuma(chType)) ? (0) : (NUM_ABS_FLAG_CTX_LUMA)); const UInt absStopIndex = ((isLuma(chType)) ? (NUM_ABS_FLAG_CTX_LUMA) : (NUM_ABS_FLAG_CTX)); for (Int ctxIdx = oneStartIndex; ctxIdx < oneStopIndex; ctxIdx++) { pcEstBitsSbac->m_greaterOneBits[ ctxIdx ][ 0 ] = ctxOne[ ctxIdx ].getEntropyBits( 0 ); pcEstBitsSbac->m_greaterOneBits[ ctxIdx ][ 1 ] = ctxOne[ ctxIdx ].getEntropyBits( 1 ); } for (Int ctxIdx = absStartIndex; ctxIdx < absStopIndex; ctxIdx++) { pcEstBitsSbac->m_levelAbsBits[ ctxIdx ][ 0 ] = ctxAbs[ ctxIdx ].getEntropyBits( 0 ); pcEstBitsSbac->m_levelAbsBits[ ctxIdx ][ 1 ] = ctxAbs[ ctxIdx ].getEntropyBits( 1 ); } } /** - Initialize our context information from the nominated source. . \param pSrc From where to copy context information. */ Void TEncSbac::xCopyContextsFrom( const TEncSbac* pSrc ) { memcpy(m_contextModels, pSrc->m_contextModels, m_numContextModels*sizeof(m_contextModels[0])); memcpy(m_golombRiceAdaptationStatistics, pSrc->m_golombRiceAdaptationStatistics, (sizeof(UInt) * RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS)); } Void TEncSbac::loadContexts ( const TEncSbac* pSrc) { xCopyContextsFrom(pSrc); } /** Performs CABAC encoding of the explicit RDPCM mode * \param rTu current TU data structure * \param compID component identifier */ Void TEncSbac::codeExplicitRdpcmMode( TComTU &rTu, const ComponentID compID ) { TComDataCU *cu = rTu.getCU(); const TComRectangle &rect = rTu.getRect(compID); const UInt absPartIdx = rTu.GetAbsPartIdxTU(compID); const UInt tuHeight = g_aucConvertToBit[rect.height]; const UInt tuWidth = g_aucConvertToBit[rect.width]; assert(tuHeight == tuWidth); assert(tuHeight < 4); UInt explicitRdpcmMode = cu->getExplicitRdpcmMode(compID, absPartIdx); if( explicitRdpcmMode == RDPCM_OFF ) { m_pcBinIf->encodeBin (0, m_explicitRdpcmFlagSCModel.get (0, toChannelType(compID), 0)); } else if( explicitRdpcmMode == RDPCM_HOR || explicitRdpcmMode == RDPCM_VER ) { m_pcBinIf->encodeBin (1, m_explicitRdpcmFlagSCModel.get (0, toChannelType(compID), 0)); if(explicitRdpcmMode == RDPCM_HOR) { m_pcBinIf->encodeBin ( 0, m_explicitRdpcmDirSCModel.get(0, toChannelType(compID), 0)); } else { m_pcBinIf->encodeBin ( 1, m_explicitRdpcmDirSCModel.get(0, toChannelType(compID), 0)); } } else { assert(0); } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncSbac.h000066400000000000000000000233241442026013100202000ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSbac.h \brief Context-adaptive entropy encoder class (header) */ #ifndef __TENCSBAC__ #define __TENCSBAC__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "TLibCommon/TComBitStream.h" #include "TLibCommon/ContextTables.h" #include "TLibCommon/ContextModel.h" #include "TLibCommon/ContextModel3DBuffer.h" #include "TEncEntropy.h" #include "TEncBinCoder.h" #include "TEncBinCoderCABAC.h" #if FAST_BIT_EST #include "TEncBinCoderCABACCounter.h" #endif class TEncTop; //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// SBAC encoder class class TEncSbac : public TEncEntropyIf { public: TEncSbac(); virtual ~TEncSbac(); Void init ( TEncBinIf* p ) { m_pcBinIf = p; } Void uninit () { m_pcBinIf = 0; } // Virtual list Void resetEntropy (const TComSlice *pSlice); SliceType determineCabacInitIdx (const TComSlice *pSlice); Void setBitstream ( TComBitIf* p ) { m_pcBitIf = p; m_pcBinIf->init( p ); } Void load ( const TEncSbac* pSrc ); Void loadIntraDirMode ( const TEncSbac* pScr, const ChannelType chType ); Void store ( TEncSbac* pDest ) const; Void loadContexts ( const TEncSbac* pSrc ); Void resetBits () { m_pcBinIf->resetBits(); m_pcBitIf->resetBits(); } UInt getNumberOfWrittenBits () { return m_pcBinIf->getNumWrittenBits(); } //--SBAC RD Void codeVPS ( const TComVPS* pcVPS ); Void codeSPS ( const TComSPS* pcSPS ); Void codePPS ( const TComPPS* pcPPS ); Void codeSliceHeader ( TComSlice* pcSlice ); Void codeTilesWPPEntryPoint ( TComSlice* pSlice ); Void codeTerminatingBit ( UInt uilsLast ); Void codeSliceFinish (); Void codeSaoMaxUvlc ( UInt code, UInt maxSymbol ); Void codeSaoMerge ( UInt uiCode ); Void codeSaoTypeIdx ( UInt uiCode); Void codeSaoUflc ( UInt uiLength, UInt uiCode ); Void codeSAOSign ( UInt uiCode); // #include //! \ingroup TLibEncoder //! \{ static const TComMv s_acMvRefineH[9] = { TComMv( 0, 0 ), // 0 TComMv( 0, -1 ), // 1 TComMv( 0, 1 ), // 2 TComMv( -1, 0 ), // 3 TComMv( 1, 0 ), // 4 TComMv( -1, -1 ), // 5 TComMv( 1, -1 ), // 6 TComMv( -1, 1 ), // 7 TComMv( 1, 1 ) // 8 }; static const TComMv s_acMvRefineQ[9] = { TComMv( 0, 0 ), // 0 TComMv( 0, -1 ), // 1 TComMv( 0, 1 ), // 2 TComMv( -1, -1 ), // 5 TComMv( 1, -1 ), // 6 TComMv( -1, 0 ), // 3 TComMv( 1, 0 ), // 4 TComMv( -1, 1 ), // 7 TComMv( 1, 1 ) // 8 }; static Void offsetSubTUCBFs(TComTU &rTu, const ComponentID compID) { TComDataCU *pcCU = rTu.getCU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(compID); const UInt partIdxesPerSubTU = rTu.GetAbsPartIdxNumParts(compID) >> 1; //move the CBFs down a level and set the parent CBF UChar subTUCBF[2]; UChar combinedSubTUCBF = 0; for (UInt subTU = 0; subTU < 2; subTU++) { const UInt subTUAbsPartIdx = uiAbsPartIdx + (subTU * partIdxesPerSubTU); subTUCBF[subTU] = pcCU->getCbf(subTUAbsPartIdx, compID, uiTrDepth); combinedSubTUCBF |= subTUCBF[subTU]; } for (UInt subTU = 0; subTU < 2; subTU++) { const UInt subTUAbsPartIdx = uiAbsPartIdx + (subTU * partIdxesPerSubTU); const UChar compositeCBF = (subTUCBF[subTU] << 1) | combinedSubTUCBF; pcCU->setCbfPartRange((compositeCBF << uiTrDepth), compID, subTUAbsPartIdx, partIdxesPerSubTU); } } TEncSearch::TEncSearch() : m_puhQTTempTrIdx(NULL) , m_pcQTTempTComYuv(NULL) , m_pcEncCfg (NULL) , m_pcTrQuant (NULL) , m_pcRdCost (NULL) , m_pcEntropyCoder (NULL) , m_iSearchRange (0) , m_bipredSearchRange (0) , m_motionEstimationSearchMethod (MESEARCH_FULL) , m_pppcRDSbacCoder (NULL) , m_pcRDGoOnSbacCoder (NULL) , m_pTempPel (NULL) , m_isInitialized (false) { for (UInt ch=0; chgetQuadtreeTULog2MaxSize()-m_pcEncCfg->getQuadtreeTULog2MinSize()+1; for (UInt ch=0; chgetChromaFormatIdc(); initTempBuff(cform); m_pTempPel = new Pel[maxCUWidth*maxCUHeight]; const UInt uiNumLayersToAllocate = pcEncCfg->getQuadtreeTULog2MaxSize()-pcEncCfg->getQuadtreeTULog2MinSize()+1; const UInt uiNumPartitions = 1<<(maxTotalCUDepth<<1); for (UInt ch=0; ch>(csx+csy)]; #if ADAPTIVE_QP_SELECTION m_ppcQTTempArlCoeff[ch][layer] = new TCoeff[(maxCUWidth*maxCUHeight)>>(csx+csy) ]; #endif } m_phQTTempCrossComponentPredictionAlpha[ch] = new SChar [uiNumPartitions]; m_pSharedPredTransformSkip[ch] = new Pel [MAX_CU_SIZE*MAX_CU_SIZE]; m_pcQTTempTUCoeff[ch] = new TCoeff[MAX_CU_SIZE*MAX_CU_SIZE]; #if ADAPTIVE_QP_SELECTION m_ppcQTTempTUArlCoeff[ch] = new TCoeff[MAX_CU_SIZE*MAX_CU_SIZE]; #endif m_puhQTTempTransformSkipFlag[ch] = new UChar [uiNumPartitions]; } m_puhQTTempTrIdx = new UChar [uiNumPartitions]; m_pcQTTempTComYuv = new TComYuv[uiNumLayersToAllocate]; for( UInt ui = 0; ui < uiNumLayersToAllocate; ++ui ) { m_pcQTTempTComYuv[ui].create( maxCUWidth, maxCUHeight, pcEncCfg->getChromaFormatIdc() ); } m_pcQTTempTransformSkipTComYuv.create( maxCUWidth, maxCUHeight, pcEncCfg->getChromaFormatIdc() ); m_tmpYuvPred.create(MAX_CU_SIZE, MAX_CU_SIZE, pcEncCfg->getChromaFormatIdc()); m_isInitialized = true; } __inline Void TEncSearch::xTZSearchHelp( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const Int iSearchX, const Int iSearchY, const UChar ucPointNr, const UInt uiDistance ) { Distortion uiSad = 0; const Pel* const piRefSrch = rcStruct.piRefY + iSearchY * rcStruct.iYStride + iSearchX; //-- jclee for using the SAD function pointer m_pcRdCost->setDistParam( pcPatternKey, piRefSrch, rcStruct.iYStride, m_cDistParam ); setDistParamComp(COMPONENT_Y); // distortion m_cDistParam.bitDepth = pcPatternKey->getBitDepthY(); m_cDistParam.m_maximumDistortionForEarlyExit = rcStruct.uiBestSad; if((m_pcEncCfg->getRestrictMESampling() == false) && m_pcEncCfg->getMotionEstimationSearchMethod() == MESEARCH_SELECTIVE) { Int isubShift = 0; // motion cost Distortion uiBitCost = m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY ); // Skip search if bit cost is already larger than best SAD if (uiBitCost < rcStruct.uiBestSad) { if ( m_cDistParam.iRows > 32 ) { m_cDistParam.iSubShift = 4; } else if ( m_cDistParam.iRows > 16 ) { m_cDistParam.iSubShift = 3; } else if ( m_cDistParam.iRows > 8 ) { m_cDistParam.iSubShift = 2; } else { m_cDistParam.iSubShift = 1; } Distortion uiTempSad = m_cDistParam.DistFunc( &m_cDistParam ); if((uiTempSad + uiBitCost) < rcStruct.uiBestSad) { uiSad += uiTempSad >> m_cDistParam.iSubShift; while(m_cDistParam.iSubShift > 0) { isubShift = m_cDistParam.iSubShift -1; m_cDistParam.pOrg = pcPatternKey->getROIY() + (pcPatternKey->getPatternLStride() << isubShift); m_cDistParam.pCur = piRefSrch + (rcStruct.iYStride << isubShift); uiTempSad = m_cDistParam.DistFunc( &m_cDistParam ); uiSad += uiTempSad >> m_cDistParam.iSubShift; if(((uiSad << isubShift) + uiBitCost) > rcStruct.uiBestSad) { break; } m_cDistParam.iSubShift--; } if(m_cDistParam.iSubShift == 0) { uiSad += uiBitCost; if( uiSad < rcStruct.uiBestSad ) { rcStruct.uiBestSad = uiSad; rcStruct.iBestX = iSearchX; rcStruct.iBestY = iSearchY; rcStruct.uiBestDistance = uiDistance; rcStruct.uiBestRound = 0; rcStruct.ucPointNr = ucPointNr; m_cDistParam.m_maximumDistortionForEarlyExit = uiSad; } } } } } else { // fast encoder decision: use subsampled SAD when rows > 8 for integer ME if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE3 ) { if ( m_cDistParam.iRows > 8 ) { m_cDistParam.iSubShift = 1; } } uiSad = m_cDistParam.DistFunc( &m_cDistParam ); // only add motion cost if uiSad is smaller than best. Otherwise pointless // to add motion cost. if( uiSad < rcStruct.uiBestSad ) { // motion cost uiSad += m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY ); if( uiSad < rcStruct.uiBestSad ) { rcStruct.uiBestSad = uiSad; rcStruct.iBestX = iSearchX; rcStruct.iBestY = iSearchY; rcStruct.uiBestDistance = uiDistance; rcStruct.uiBestRound = 0; rcStruct.ucPointNr = ucPointNr; m_cDistParam.m_maximumDistortionForEarlyExit = uiSad; } } } } __inline Void TEncSearch::xTZ2PointSearch( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB ) { Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); // 2 point search, // 1 2 3 // check only the 2 untested points // 4 0 5 // around the start point // 6 7 8 Int iStartX = rcStruct.iBestX; Int iStartY = rcStruct.iBestY; switch( rcStruct.ucPointNr ) { case 1: { if ( (iStartX - 1) >= iSrchRngHorLeft ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY, 0, 2 ); } if ( (iStartY - 1) >= iSrchRngVerTop ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY - 1, 0, 2 ); } } break; case 2: { if ( (iStartY - 1) >= iSrchRngVerTop ) { if ( (iStartX - 1) >= iSrchRngHorLeft ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY - 1, 0, 2 ); } if ( (iStartX + 1) <= iSrchRngHorRight ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY - 1, 0, 2 ); } } } break; case 3: { if ( (iStartY - 1) >= iSrchRngVerTop ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY - 1, 0, 2 ); } if ( (iStartX + 1) <= iSrchRngHorRight ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY, 0, 2 ); } } break; case 4: { if ( (iStartX - 1) >= iSrchRngHorLeft ) { if ( (iStartY + 1) <= iSrchRngVerBottom ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY + 1, 0, 2 ); } if ( (iStartY - 1) >= iSrchRngVerTop ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY - 1, 0, 2 ); } } } break; case 5: { if ( (iStartX + 1) <= iSrchRngHorRight ) { if ( (iStartY - 1) >= iSrchRngVerTop ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY - 1, 0, 2 ); } if ( (iStartY + 1) <= iSrchRngVerBottom ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY + 1, 0, 2 ); } } } break; case 6: { if ( (iStartX - 1) >= iSrchRngHorLeft ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY , 0, 2 ); } if ( (iStartY + 1) <= iSrchRngVerBottom ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY + 1, 0, 2 ); } } break; case 7: { if ( (iStartY + 1) <= iSrchRngVerBottom ) { if ( (iStartX - 1) >= iSrchRngHorLeft ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX - 1, iStartY + 1, 0, 2 ); } if ( (iStartX + 1) <= iSrchRngHorRight ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY + 1, 0, 2 ); } } } break; case 8: { if ( (iStartX + 1) <= iSrchRngHorRight ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX + 1, iStartY, 0, 2 ); } if ( (iStartY + 1) <= iSrchRngVerBottom ) { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iStartY + 1, 0, 2 ); } } break; default: { assert( false ); } break; } // switch( rcStruct.ucPointNr ) } __inline Void TEncSearch::xTZ8PointSquareSearch( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, const Int iStartX, const Int iStartY, const Int iDist ) { const Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); const Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); const Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); const Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); // 8 point search, // 1 2 3 // search around the start point // 4 0 5 // with the required distance // 6 7 8 assert( iDist != 0 ); const Int iTop = iStartY - iDist; const Int iBottom = iStartY + iDist; const Int iLeft = iStartX - iDist; const Int iRight = iStartX + iDist; rcStruct.uiBestRound += 1; if ( iTop >= iSrchRngVerTop ) // check top { if ( iLeft >= iSrchRngHorLeft ) // check top left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iTop, 1, iDist ); } // top middle xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist ); if ( iRight <= iSrchRngHorRight ) // check top right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iTop, 3, iDist ); } } // check top if ( iLeft >= iSrchRngHorLeft ) // check middle left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist ); } if ( iRight <= iSrchRngHorRight ) // check middle right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist ); } if ( iBottom <= iSrchRngVerBottom ) // check bottom { if ( iLeft >= iSrchRngHorLeft ) // check bottom left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iBottom, 6, iDist ); } // check bottom middle xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist ); if ( iRight <= iSrchRngHorRight ) // check bottom right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iBottom, 8, iDist ); } } // check bottom } __inline Void TEncSearch::xTZ8PointDiamondSearch( const TComPattern*const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv*const pcMvSrchRngLT, const TComMv*const pcMvSrchRngRB, const Int iStartX, const Int iStartY, const Int iDist, const Bool bCheckCornersAtDist1 ) { const Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); const Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); const Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); const Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); // 8 point search, // 1 2 3 // search around the start point // 4 0 5 // with the required distance // 6 7 8 assert ( iDist != 0 ); const Int iTop = iStartY - iDist; const Int iBottom = iStartY + iDist; const Int iLeft = iStartX - iDist; const Int iRight = iStartX + iDist; rcStruct.uiBestRound += 1; if ( iDist == 1 ) { if ( iTop >= iSrchRngVerTop ) // check top { if (bCheckCornersAtDist1) { if ( iLeft >= iSrchRngHorLeft) // check top-left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iTop, 1, iDist ); } xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist ); if ( iRight <= iSrchRngHorRight ) // check middle right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iTop, 3, iDist ); } } else { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist ); } } if ( iLeft >= iSrchRngHorLeft ) // check middle left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist ); } if ( iRight <= iSrchRngHorRight ) // check middle right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist ); } if ( iBottom <= iSrchRngVerBottom ) // check bottom { if (bCheckCornersAtDist1) { if ( iLeft >= iSrchRngHorLeft) // check top-left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iBottom, 6, iDist ); } xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist ); if ( iRight <= iSrchRngHorRight ) // check middle right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iBottom, 8, iDist ); } } else { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist ); } } } else { if ( iDist <= 8 ) { const Int iTop_2 = iStartY - (iDist>>1); const Int iBottom_2 = iStartY + (iDist>>1); const Int iLeft_2 = iStartX - (iDist>>1); const Int iRight_2 = iStartX + (iDist>>1); if ( iTop >= iSrchRngVerTop && iLeft >= iSrchRngHorLeft && iRight <= iSrchRngHorRight && iBottom <= iSrchRngVerBottom ) // check border { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iTop_2, 1, iDist>>1 ); xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iTop_2, 3, iDist>>1 ); xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iBottom_2, 6, iDist>>1 ); xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iBottom_2, 8, iDist>>1 ); xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist ); } else // check border { if ( iTop >= iSrchRngVerTop ) // check top { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 2, iDist ); } if ( iTop_2 >= iSrchRngVerTop ) // check half top { if ( iLeft_2 >= iSrchRngHorLeft ) // check half left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iTop_2, 1, (iDist>>1) ); } if ( iRight_2 <= iSrchRngHorRight ) // check half right { xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iTop_2, 3, (iDist>>1) ); } } // check half top if ( iLeft >= iSrchRngHorLeft ) // check left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 4, iDist ); } if ( iRight <= iSrchRngHorRight ) // check right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 5, iDist ); } if ( iBottom_2 <= iSrchRngVerBottom ) // check half bottom { if ( iLeft_2 >= iSrchRngHorLeft ) // check half left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft_2, iBottom_2, 6, (iDist>>1) ); } if ( iRight_2 <= iSrchRngHorRight ) // check half right { xTZSearchHelp( pcPatternKey, rcStruct, iRight_2, iBottom_2, 8, (iDist>>1) ); } } // check half bottom if ( iBottom <= iSrchRngVerBottom ) // check bottom { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 7, iDist ); } } // check border } else // iDist > 8 { if ( iTop >= iSrchRngVerTop && iLeft >= iSrchRngHorLeft && iRight <= iSrchRngHorRight && iBottom <= iSrchRngVerBottom ) // check border { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 0, iDist ); for ( Int index = 1; index < 4; index++ ) { const Int iPosYT = iTop + ((iDist>>2) * index); const Int iPosYB = iBottom - ((iDist>>2) * index); const Int iPosXL = iStartX - ((iDist>>2) * index); const Int iPosXR = iStartX + ((iDist>>2) * index); xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYT, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYT, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYB, 0, iDist ); xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYB, 0, iDist ); } } else // check border { if ( iTop >= iSrchRngVerTop ) // check top { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iTop, 0, iDist ); } if ( iLeft >= iSrchRngHorLeft ) // check left { xTZSearchHelp( pcPatternKey, rcStruct, iLeft, iStartY, 0, iDist ); } if ( iRight <= iSrchRngHorRight ) // check right { xTZSearchHelp( pcPatternKey, rcStruct, iRight, iStartY, 0, iDist ); } if ( iBottom <= iSrchRngVerBottom ) // check bottom { xTZSearchHelp( pcPatternKey, rcStruct, iStartX, iBottom, 0, iDist ); } for ( Int index = 1; index < 4; index++ ) { const Int iPosYT = iTop + ((iDist>>2) * index); const Int iPosYB = iBottom - ((iDist>>2) * index); const Int iPosXL = iStartX - ((iDist>>2) * index); const Int iPosXR = iStartX + ((iDist>>2) * index); if ( iPosYT >= iSrchRngVerTop ) // check top { if ( iPosXL >= iSrchRngHorLeft ) // check left { xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYT, 0, iDist ); } if ( iPosXR <= iSrchRngHorRight ) // check right { xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYT, 0, iDist ); } } // check top if ( iPosYB <= iSrchRngVerBottom ) // check bottom { if ( iPosXL >= iSrchRngHorLeft ) // check left { xTZSearchHelp( pcPatternKey, rcStruct, iPosXL, iPosYB, 0, iDist ); } if ( iPosXR <= iSrchRngHorRight ) // check right { xTZSearchHelp( pcPatternKey, rcStruct, iPosXR, iPosYB, 0, iDist ); } } // check bottom } // for ... } // check border } // iDist <= 8 } // iDist == 1 } Distortion TEncSearch::xPatternRefinement( TComPattern* pcPatternKey, TComMv baseRefMv, Int iFrac, TComMv& rcMvFrac, Bool bAllowUseOfHadamard ) { Distortion uiDist; Distortion uiDistBest = std::numeric_limits::max(); UInt uiDirecBest = 0; Pel* piRefPos; Int iRefStride = m_filteredBlock[0][0].getStride(COMPONENT_Y); m_pcRdCost->setDistParam( pcPatternKey, m_filteredBlock[0][0].getAddr(COMPONENT_Y), iRefStride, 1, m_cDistParam, m_pcEncCfg->getUseHADME() && bAllowUseOfHadamard ); const TComMv* pcMvRefine = (iFrac == 2 ? s_acMvRefineH : s_acMvRefineQ); #if MCTS_ENC_CHECK UInt maxRefinements = 9; Int mvShift = 2; // filter length of sub-sample generation filter to be considered const UInt LumaLTSampleOffset = 3; const UInt LumaRBSampleOffset = 4; if (m_pcEncCfg->getTMCTSSEITileConstraint()) { // if close to tile borders if ( pcPatternKey->getROIYPosX() + (baseRefMv.getHor() >> mvShift ) < pcPatternKey->getTileLeftTopPelPosX() + LumaLTSampleOffset || pcPatternKey->getROIYPosY() + (baseRefMv.getVer() >> mvShift ) < pcPatternKey->getTileLeftTopPelPosY() + LumaLTSampleOffset || pcPatternKey->getROIYPosX() + (baseRefMv.getHor() >> mvShift) > pcPatternKey->getTileRightBottomPelPosX() - pcPatternKey->getROIYWidth() - LumaRBSampleOffset || pcPatternKey->getROIYPosY() + (baseRefMv.getVer() >> mvShift) > pcPatternKey->getTileRightBottomPelPosY() - pcPatternKey->getROIYHeight() - LumaRBSampleOffset ) { // only allow full pel positions to avoid filter dependency maxRefinements = 1; } } for (UInt i = 0; i < maxRefinements; i++) #else for (UInt i = 0; i < 9; i++) #endif { TComMv cMvTest = pcMvRefine[i]; cMvTest += baseRefMv; Int horVal = cMvTest.getHor() * iFrac; Int verVal = cMvTest.getVer() * iFrac; piRefPos = m_filteredBlock[ verVal & 3 ][ horVal & 3 ].getAddr(COMPONENT_Y); if ( horVal == 2 && ( verVal & 1 ) == 0 ) { piRefPos += 1; } if ( ( horVal & 1 ) == 0 && verVal == 2 ) { piRefPos += iRefStride; } cMvTest = pcMvRefine[i]; cMvTest += rcMvFrac; setDistParamComp(COMPONENT_Y); m_cDistParam.pCur = piRefPos; m_cDistParam.bitDepth = pcPatternKey->getBitDepthY(); uiDist = m_cDistParam.DistFunc( &m_cDistParam ); uiDist += m_pcRdCost->getCostOfVectorWithPredictor( cMvTest.getHor(), cMvTest.getVer() ); if ( uiDist < uiDistBest ) { uiDistBest = uiDist; uiDirecBest = i; m_cDistParam.m_maximumDistortionForEarlyExit = uiDist; } } rcMvFrac = pcMvRefine[uiDirecBest]; return uiDistBest; } Void TEncSearch::xEncSubdivCbfQT(TComTU &rTu, Bool bLuma, Bool bChroma ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); const UInt uiSubdiv = ( uiTrMode > uiTrDepth ? 1 : 0 ); const UInt uiLog2LumaTrafoSize = rTu.GetLog2LumaTrSize(); if( pcCU->isIntra(0) && pcCU->getPartitionSize(0) == SIZE_NxN && uiTrDepth == 0 ) { assert( uiSubdiv ); } else if( uiLog2LumaTrafoSize > pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ) { assert( uiSubdiv ); } else if( uiLog2LumaTrafoSize == pcCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) { assert( !uiSubdiv ); } else if( uiLog2LumaTrafoSize == pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { assert( !uiSubdiv ); } else { assert( uiLog2LumaTrafoSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); if( bLuma ) { m_pcEntropyCoder->encodeTransformSubdivFlag( uiSubdiv, 5 - uiLog2LumaTrafoSize ); } } if ( bChroma ) { const UInt numberValidComponents = getNumberValidComponents(rTu.GetChromaFormat()); for (UInt ch=COMPONENT_Cb; chgetCbf( uiAbsPartIdx, compID, uiTrDepth-1 ) )) { m_pcEntropyCoder->encodeQtCbf(rTu, compID, (uiSubdiv == 0)); } } } if( uiSubdiv ) { TComTURecurse tuRecurse(rTu, false); do { xEncSubdivCbfQT( tuRecurse, bLuma, bChroma ); } while (tuRecurse.nextSection(rTu)); } else { //===== Cbfs ===== if( bLuma ) { m_pcEntropyCoder->encodeQtCbf( rTu, COMPONENT_Y, true ); } } } Void TEncSearch::xEncCoeffQT(TComTU &rTu, const ComponentID component, Bool bRealCoeff ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrDepth=rTu.GetTransformDepthRel(); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); const UInt uiSubdiv = ( uiTrMode > uiTrDepth ? 1 : 0 ); if( uiSubdiv ) { TComTURecurse tuRecurseChild(rTu, false); do { xEncCoeffQT( tuRecurseChild, component, bRealCoeff ); } while (tuRecurseChild.nextSection(rTu) ); } else if (rTu.ProcessComponentSection(component)) { //===== coefficients ===== const UInt uiLog2TrafoSize = rTu.GetLog2LumaTrSize(); UInt uiCoeffOffset = rTu.getCoefficientOffset(component); UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrafoSize; TCoeff* pcCoeff = bRealCoeff ? pcCU->getCoeff(component) : m_ppcQTTempCoeff[component][uiQTLayer]; if (isChroma(component) && (pcCU->getCbf( rTu.GetAbsPartIdxTU(), COMPONENT_Y, uiTrMode ) != 0) && pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() ) { m_pcEntropyCoder->encodeCrossComponentPrediction( rTu, component ); } m_pcEntropyCoder->encodeCoeffNxN( rTu, pcCoeff+uiCoeffOffset, component ); } } Void TEncSearch::xEncIntraHeader( TComDataCU* pcCU, UInt uiTrDepth, UInt uiAbsPartIdx, Bool bLuma, Bool bChroma ) { if( bLuma ) { // CU header if( uiAbsPartIdx == 0 ) { if( !pcCU->getSlice()->isIntra() ) { if (pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag( pcCU, 0, true ); } m_pcEntropyCoder->encodeSkipFlag( pcCU, 0, true ); m_pcEntropyCoder->encodePredMode( pcCU, 0, true ); } m_pcEntropyCoder ->encodePartSize( pcCU, 0, pcCU->getDepth(0), true ); if (pcCU->isIntra(0) && pcCU->getPartitionSize(0) == SIZE_2Nx2N ) { m_pcEntropyCoder->encodeIPCMInfo( pcCU, 0, true ); if ( pcCU->getIPCMFlag (0)) { return; } } } // luma prediction mode if( pcCU->getPartitionSize(0) == SIZE_2Nx2N ) { if (uiAbsPartIdx==0) { m_pcEntropyCoder->encodeIntraDirModeLuma ( pcCU, 0 ); } } else { UInt uiQNumParts = pcCU->getTotalNumPart() >> 2; if (uiTrDepth>0 && (uiAbsPartIdx%uiQNumParts)==0) { m_pcEntropyCoder->encodeIntraDirModeLuma ( pcCU, uiAbsPartIdx ); } } } if( bChroma ) { if( pcCU->getPartitionSize(0) == SIZE_2Nx2N || !enable4ChromaPUsInIntraNxNCU(pcCU->getPic()->getChromaFormat())) { if(uiAbsPartIdx==0) { m_pcEntropyCoder->encodeIntraDirModeChroma ( pcCU, uiAbsPartIdx ); } } else { UInt uiQNumParts = pcCU->getTotalNumPart() >> 2; assert(uiTrDepth>0); if ((uiAbsPartIdx%uiQNumParts)==0) { m_pcEntropyCoder->encodeIntraDirModeChroma ( pcCU, uiAbsPartIdx ); } } } } UInt TEncSearch::xGetIntraBitsQT(TComTU &rTu, Bool bLuma, Bool bChroma, Bool bRealCoeff /* just for test */ ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrDepth=rTu.GetTransformDepthRel(); m_pcEntropyCoder->resetBits(); xEncIntraHeader ( pcCU, uiTrDepth, uiAbsPartIdx, bLuma, bChroma ); xEncSubdivCbfQT ( rTu, bLuma, bChroma ); if( bLuma ) { xEncCoeffQT ( rTu, COMPONENT_Y, bRealCoeff ); } if( bChroma ) { xEncCoeffQT ( rTu, COMPONENT_Cb, bRealCoeff ); xEncCoeffQT ( rTu, COMPONENT_Cr, bRealCoeff ); } UInt uiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); return uiBits; } UInt TEncSearch::xGetIntraBitsQTChroma(TComTU &rTu, ComponentID compID, Bool bRealCoeff /* just for test */ ) { m_pcEntropyCoder->resetBits(); xEncCoeffQT ( rTu, compID, bRealCoeff ); UInt uiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); return uiBits; } Void TEncSearch::xIntraCodingTUBlock( TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE], const Bool checkCrossCPrediction, Distortion& ruiDist, const ComponentID compID, TComTU& rTu DEBUG_STRING_FN_DECLARE(sDebug) ,Int default0Save1Load2 ) { if (!rTu.ProcessComponentSection(compID)) { return; } const Bool bIsLuma = isLuma(compID); const TComRectangle &rect = rTu.getRect(compID); TComDataCU *pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiTrDepth = rTu.GetTransformDepthRelAdj(compID); const UInt uiFullDepth = rTu.GetTransformDepthTotal(); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const ChromaFormat chFmt = pcOrgYuv->getChromaFormat(); const ChannelType chType = toChannelType(compID); const Int bitDepth = sps.getBitDepth(chType); const UInt uiWidth = rect.width; const UInt uiHeight = rect.height; const UInt uiStride = pcOrgYuv ->getStride (compID); Pel *piOrg = pcOrgYuv ->getAddr( compID, uiAbsPartIdx ); Pel *piPred = pcPredYuv->getAddr( compID, uiAbsPartIdx ); Pel *piResi = pcResiYuv->getAddr( compID, uiAbsPartIdx ); Pel *piReco = pcPredYuv->getAddr( compID, uiAbsPartIdx ); const UInt uiQTLayer = sps.getQuadtreeTULog2MaxSize() - uiLog2TrSize; Pel *piRecQt = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx ); const UInt uiRecQtStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride(compID); const UInt uiZOrder = pcCU->getZorderIdxInCtu() + uiAbsPartIdx; Pel *piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), uiZOrder ); UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride ( compID ); TCoeff *pcCoeff = m_ppcQTTempCoeff[compID][uiQTLayer] + rTu.getCoefficientOffset(compID); Bool useTransformSkip = pcCU->getTransformSkip(uiAbsPartIdx, compID); #if ADAPTIVE_QP_SELECTION TCoeff *pcArlCoeff = m_ppcQTTempArlCoeff[compID][ uiQTLayer ] + rTu.getCoefficientOffset(compID); #endif const UInt uiChPredMode = pcCU->getIntraDir( chType, uiAbsPartIdx ); const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize())); const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode; const UInt uiChFinalMode = ((chFmt == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; const Int blkX = g_auiRasterToPelX[ g_auiZscanToRaster[ uiAbsPartIdx ] ]; const Int blkY = g_auiRasterToPelY[ g_auiZscanToRaster[ uiAbsPartIdx ] ]; const Int bufferOffset = blkX + (blkY * MAX_CU_SIZE); Pel *const encoderLumaResidual = resiLuma[RESIDUAL_ENCODER_SIDE ] + bufferOffset; Pel *const reconstructedLumaResidual = resiLuma[RESIDUAL_RECONSTRUCTED] + bufferOffset; const Bool bUseCrossCPrediction = isChroma(compID) && (uiChPredMode == DM_CHROMA_IDX) && checkCrossCPrediction; const Bool bUseReconstructedResidualForEstimate = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate(); Pel *const lumaResidualForEstimate = bUseReconstructedResidualForEstimate ? reconstructedLumaResidual : encoderLumaResidual; #if DEBUG_STRING const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA); #endif //===== init availability pattern ===== DEBUG_STRING_NEW(sTemp) #if !DEBUG_STRING if( default0Save1Load2 != 2 ) #endif { const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()); initIntraPatternChType( rTu, compID, bUseFilteredPredictions DEBUG_STRING_PASS_INTO(sDebug) ); //===== get prediction signal ===== predIntraAng( compID, uiChFinalMode, piOrg, uiStride, piPred, uiStride, rTu, bUseFilteredPredictions ); // save prediction if( default0Save1Load2 == 1 ) { Pel* pPred = piPred; Pel* pPredBuf = m_pSharedPredTransformSkip[compID]; Int k = 0; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pPredBuf[ k ++ ] = pPred[ uiX ]; } pPred += uiStride; } } } #if !DEBUG_STRING else { // load prediction Pel* pPred = piPred; Pel* pPredBuf = m_pSharedPredTransformSkip[compID]; Int k = 0; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pPred[ uiX ] = pPredBuf[ k ++ ]; } pPred += uiStride; } } #endif //===== get residual signal ===== { // get residual Pel* pOrg = piOrg; Pel* pPred = piPred; Pel* pResi = piResi; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pResi[ uiX ] = pOrg[ uiX ] - pPred[ uiX ]; } pOrg += uiStride; pResi += uiStride; pPred += uiStride; } } if (pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { if (bUseCrossCPrediction) { if (xCalcCrossComponentPredictionAlpha( rTu, compID, lumaResidualForEstimate, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride ) == 0) { return; } TComTrQuant::crossComponentPrediction ( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, false ); } else if (isLuma(compID) && !bUseReconstructedResidualForEstimate) { xStoreCrossComponentPredictionResult( encoderLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride ); } } //===== transform and quantization ===== //--- init rate estimation arrays for RDOQ --- if( useTransformSkip ? m_pcEncCfg->getUseRDOQTS() : m_pcEncCfg->getUseRDOQ() ) { COEFF_SCAN_TYPE scanType = COEFF_SCAN_TYPE(pcCU->getCoefScanIdx(uiAbsPartIdx, uiWidth, uiHeight, compID)); m_pcEntropyCoder->estimateBit( m_pcTrQuant->m_pcEstBitsSbac, uiWidth, uiHeight, chType, scanType ); } //--- transform and quantization --- TCoeff uiAbsSum = 0; if (bIsLuma) { pcCU ->setTrIdxSubParts ( uiTrDepth, uiAbsPartIdx, uiFullDepth ); } const QpParam cQP(*pcCU, compID); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda (compID); #endif m_pcTrQuant->transformNxN ( rTu, compID, piResi, uiStride, pcCoeff, #if ADAPTIVE_QP_SELECTION pcArlCoeff, #endif uiAbsSum, cQP ); //--- inverse transform --- #if DEBUG_STRING if ( (uiAbsSum > 0) || (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ) #else if ( uiAbsSum > 0 ) #endif { m_pcTrQuant->invTransformNxN ( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO_OPTIONAL(&sDebug, (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask)) ); } else { Pel* pResi = piResi; memset( pcCoeff, 0, sizeof( TCoeff ) * uiWidth * uiHeight ); for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { memset( pResi, 0, sizeof( Pel ) * uiWidth ); pResi += uiStride; } } //===== reconstruction ===== { Pel* pPred = piPred; Pel* pResi = piResi; Pel* pReco = piReco; Pel* pRecQt = piRecQt; Pel* pRecIPred = piRecIPred; if (pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, true ); } else if (isLuma(compID)) { xStoreCrossComponentPredictionResult( reconstructedLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride ); } } #if DEBUG_STRING std::stringstream ss(stringstream::out); const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); if (bDebugPred || bDebugResi || bDebugReco) { ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << "\n"; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { ss << "###: "; if (bDebugPred) { ss << " - pred: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pPred[ uiX ] << ", "; } } if (bDebugResi) { ss << " - resi: "; } for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { if (bDebugResi) { ss << pResi[ uiX ] << ", "; } pReco [ uiX ] = Pel(ClipBD( Int(pPred[uiX]) + Int(pResi[uiX]), bitDepth )); pRecQt [ uiX ] = pReco[ uiX ]; pRecIPred[ uiX ] = pReco[ uiX ]; } if (bDebugReco) { ss << " - reco: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pReco[ uiX ] << ", "; } } pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecQt += uiRecQtStride; pRecIPred += uiRecIPredStride; ss << "\n"; } DEBUG_STRING_APPEND(sDebug, ss.str()) } else #endif { for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pReco [ uiX ] = Pel(ClipBD( Int(pPred[uiX]) + Int(pResi[uiX]), bitDepth )); pRecQt [ uiX ] = pReco[ uiX ]; pRecIPred[ uiX ] = pReco[ uiX ]; } pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecQt += uiRecQtStride; pRecIPred += uiRecIPredStride; } } } //===== update distortion ===== ruiDist += m_pcRdCost->getDistPart( bitDepth, piReco, uiStride, piOrg, uiStride, uiWidth, uiHeight, compID ); } Void TEncSearch::xRecurIntraCodingLumaQT(TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE], Distortion& ruiDistY, #if HHI_RQT_INTRA_SPEEDUP Bool bCheckFirst, #endif Double& dRDCost, TComTU& rTu DEBUG_STRING_FN_DECLARE(sDebug)) { TComDataCU *pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiFullDepth = rTu.GetTransformDepthTotal(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); Bool bCheckFull = ( uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ); Bool bCheckSplit = ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); Pel resiLumaSplit [NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE]; Pel resiLumaSingle[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE]; Bool bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES]; for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++) { bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise } bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate()); #if HHI_RQT_INTRA_SPEEDUP Int maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize(); Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE); // don't check split if TU size is less or equal to max TU size Bool noSplitIntraMaxTuSize = bCheckFull; if(m_pcEncCfg->getRDpenalty() && ! isIntraSlice) { // in addition don't check split if TU size is less or equal to 16x16 TU size for non-intra slice noSplitIntraMaxTuSize = ( uiLog2TrSize <= min(maxTuSize,4) ); // if maximum RD-penalty don't check TU size 32x32 if(m_pcEncCfg->getRDpenalty()==2) { bCheckFull = ( uiLog2TrSize <= min(maxTuSize,4)); } } if( bCheckFirst && noSplitIntraMaxTuSize ) { bCheckSplit = false; } #else Int maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize(); Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE); // if maximum RD-penalty don't check TU size 32x32 if((m_pcEncCfg->getRDpenalty()==2) && !isIntraSlice) { bCheckFull = ( uiLog2TrSize <= min(maxTuSize,4)); } #endif Double dSingleCost = MAX_DOUBLE; Distortion uiSingleDistLuma = 0; UInt uiSingleCbfLuma = 0; Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip(); Int bestModeId[MAX_NUM_COMPONENT] = { 0, 0, 0}; checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()); checkTransformSkip &= (!pcCU->getCUTransquantBypass(0)); assert (rTu.ProcessComponentSection(COMPONENT_Y)); const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(COMPONENT_Y); if ( m_pcEncCfg->getUseTransformSkipFast() ) { checkTransformSkip &= (pcCU->getPartitionSize(uiAbsPartIdx)==SIZE_NxN); } if( bCheckFull ) { if(checkTransformSkip == true) { //----- store original entropy coding status ----- m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); Distortion singleDistTmpLuma = 0; UInt singleCbfTmpLuma = 0; Double singleCostTmp = 0; Int firstCheckId = 0; for(Int modeId = firstCheckId; modeId < 2; modeId ++) { DEBUG_STRING_NEW(sModeString) Int default0Save1Load2 = 0; singleDistTmpLuma=0; if(modeId == firstCheckId) { default0Save1Load2 = 1; } else { default0Save1Load2 = 2; } pcCU->setTransformSkipSubParts ( modeId, COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan ); xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle, false, singleDistTmpLuma, COMPONENT_Y, rTu DEBUG_STRING_PASS_INTO(sModeString), default0Save1Load2 ); singleCbfTmpLuma = pcCU->getCbf( uiAbsPartIdx, COMPONENT_Y, uiTrDepth ); //----- determine rate and r-d cost ----- if(modeId == 1 && singleCbfTmpLuma == 0) { //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. singleCostTmp = MAX_DOUBLE; } else { UInt uiSingleBits = xGetIntraBitsQT( rTu, true, false, false ); singleCostTmp = m_pcRdCost->calcRdCost( uiSingleBits, singleDistTmpLuma ); } if(singleCostTmp < dSingleCost) { DEBUG_STRING_SWAP(sDebug, sModeString) dSingleCost = singleCostTmp; uiSingleDistLuma = singleDistTmpLuma; uiSingleCbfLuma = singleCbfTmpLuma; bestModeId[COMPONENT_Y] = modeId; if(bestModeId[COMPONENT_Y] == firstCheckId) { xStoreIntraResultQT(COMPONENT_Y, rTu ); m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } if (pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } } if (modeId == firstCheckId) { m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } } pcCU ->setTransformSkipSubParts ( bestModeId[COMPONENT_Y], COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan ); if(bestModeId[COMPONENT_Y] == firstCheckId) { xLoadIntraResultQT(COMPONENT_Y, rTu ); pcCU->setCbfSubParts ( uiSingleCbfLuma << uiTrDepth, COMPONENT_Y, uiAbsPartIdx, rTu.GetTransformDepthTotalAdj(COMPONENT_Y) ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } } else { //----- store original entropy coding status ----- if( bCheckSplit ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } //----- code luma/chroma block with given intra prediction mode and store Cbf----- dSingleCost = 0.0; pcCU ->setTransformSkipSubParts ( 0, COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan ); xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle, false, uiSingleDistLuma, COMPONENT_Y, rTu DEBUG_STRING_PASS_INTO(sDebug)); if( bCheckSplit ) { uiSingleCbfLuma = pcCU->getCbf( uiAbsPartIdx, COMPONENT_Y, uiTrDepth ); } //----- determine rate and r-d cost ----- UInt uiSingleBits = xGetIntraBitsQT( rTu, true, false, false ); if(m_pcEncCfg->getRDpenalty() && (uiLog2TrSize==5) && !isIntraSlice) { uiSingleBits=uiSingleBits*4; } dSingleCost = m_pcRdCost->calcRdCost( uiSingleBits, uiSingleDistLuma ); if (pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } } } if( bCheckSplit ) { //----- store full entropy coding status, load original entropy coding status ----- if( bCheckFull ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] ); m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } else { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } //----- code splitted block ----- Double dSplitCost = 0.0; Distortion uiSplitDistLuma = 0; UInt uiSplitCbfLuma = 0; TComTURecurse tuRecurseChild(rTu, false); DEBUG_STRING_NEW(sSplit) do { DEBUG_STRING_NEW(sChild) #if HHI_RQT_INTRA_SPEEDUP xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDistLuma, bCheckFirst, dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) ); #else xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDistLuma, dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) ); #endif DEBUG_STRING_APPEND(sSplit, sChild) uiSplitCbfLuma |= pcCU->getCbf( tuRecurseChild.GetAbsPartIdxTU(), COMPONENT_Y, tuRecurseChild.GetTransformDepthRel() ); } while (tuRecurseChild.nextSection(rTu) ); UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts(); { if (uiSplitCbfLuma) { const UInt flag=1<getCbf( COMPONENT_Y ); for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ ) { pBase[ uiAbsPartIdx + uiOffs ] |= flag; } } } //----- restore context states ----- m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); //----- determine rate and r-d cost ----- UInt uiSplitBits = xGetIntraBitsQT( rTu, true, false, false ); dSplitCost = m_pcRdCost->calcRdCost( uiSplitBits, uiSplitDistLuma ); //===== compare and set best ===== if( dSplitCost < dSingleCost ) { //--- update cost --- DEBUG_STRING_SWAP(sSplit, sDebug) ruiDistY += uiSplitDistLuma; dRDCost += dSplitCost; if (pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSplit[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } return; } //----- set entropy coding status ----- m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] ); //--- set transform index and Cbf values --- pcCU->setTrIdxSubParts( uiTrDepth, uiAbsPartIdx, uiFullDepth ); const TComRectangle &tuRect=rTu.getRect(COMPONENT_Y); pcCU->setCbfSubParts ( uiSingleCbfLuma << uiTrDepth, COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan ); pcCU ->setTransformSkipSubParts ( bestModeId[COMPONENT_Y], COMPONENT_Y, uiAbsPartIdx, totalAdjustedDepthChan ); //--- set reconstruction for next intra prediction blocks --- const UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; const UInt uiZOrder = pcCU->getZorderIdxInCtu() + uiAbsPartIdx; const UInt uiWidth = tuRect.width; const UInt uiHeight = tuRect.height; Pel* piSrc = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( COMPONENT_Y, uiAbsPartIdx ); UInt uiSrcStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride ( COMPONENT_Y ); Pel* piDes = pcCU->getPic()->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), uiZOrder ); UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride ( COMPONENT_Y ); for( UInt uiY = 0; uiY < uiHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { piDes[ uiX ] = piSrc[ uiX ]; } } } ruiDistY += uiSingleDistLuma; dRDCost += dSingleCost; } Void TEncSearch::xSetIntraResultLumaQT(TComYuv* pcRecoYuv, TComTU &rTu) { TComDataCU *pcCU = rTu.getCU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); if( uiTrMode == uiTrDepth ) { UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; //===== copy transform coefficients ===== const TComRectangle &tuRect=rTu.getRect(COMPONENT_Y); const UInt coeffOffset = rTu.getCoefficientOffset(COMPONENT_Y); const UInt numCoeffInBlock = tuRect.width * tuRect.height; if (numCoeffInBlock!=0) { const TCoeff* srcCoeff = m_ppcQTTempCoeff[COMPONENT_Y][uiQTLayer] + coeffOffset; TCoeff* destCoeff = pcCU->getCoeff(COMPONENT_Y) + coeffOffset; ::memcpy( destCoeff, srcCoeff, sizeof(TCoeff)*numCoeffInBlock ); #if ADAPTIVE_QP_SELECTION const TCoeff* srcArlCoeff = m_ppcQTTempArlCoeff[COMPONENT_Y][ uiQTLayer ] + coeffOffset; TCoeff* destArlCoeff = pcCU->getArlCoeff (COMPONENT_Y) + coeffOffset; ::memcpy( destArlCoeff, srcArlCoeff, sizeof( TCoeff ) * numCoeffInBlock ); #endif m_pcQTTempTComYuv[ uiQTLayer ].copyPartToPartComponent( COMPONENT_Y, pcRecoYuv, uiAbsPartIdx, tuRect.width, tuRect.height ); } } else { TComTURecurse tuRecurseChild(rTu, false); do { xSetIntraResultLumaQT( pcRecoYuv, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } } Void TEncSearch::xStoreIntraResultQT(const ComponentID compID, TComTU &rTu ) { TComDataCU *pcCU=rTu.getCU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); if ( compID==COMPONENT_Y || uiTrMode == uiTrDepth ) { assert(uiTrMode == uiTrDepth); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; if (rTu.ProcessComponentSection(compID)) { const TComRectangle &tuRect=rTu.getRect(compID); //===== copy transform coefficients ===== const UInt uiNumCoeff = tuRect.width * tuRect.height; TCoeff* pcCoeffSrc = m_ppcQTTempCoeff[compID] [ uiQTLayer ] + rTu.getCoefficientOffset(compID); TCoeff* pcCoeffDst = m_pcQTTempTUCoeff[compID]; ::memcpy( pcCoeffDst, pcCoeffSrc, sizeof( TCoeff ) * uiNumCoeff ); #if ADAPTIVE_QP_SELECTION TCoeff* pcArlCoeffSrc = m_ppcQTTempArlCoeff[compID] [ uiQTLayer ] + rTu.getCoefficientOffset(compID); TCoeff* pcArlCoeffDst = m_ppcQTTempTUArlCoeff[compID]; ::memcpy( pcArlCoeffDst, pcArlCoeffSrc, sizeof( TCoeff ) * uiNumCoeff ); #endif //===== copy reconstruction ===== m_pcQTTempTComYuv[ uiQTLayer ].copyPartToPartComponent( compID, &m_pcQTTempTransformSkipTComYuv, uiAbsPartIdx, tuRect.width, tuRect.height ); } } } Void TEncSearch::xLoadIntraResultQT(const ComponentID compID, TComTU &rTu) { TComDataCU *pcCU=rTu.getCU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); if ( compID==COMPONENT_Y || uiTrMode == uiTrDepth ) { assert(uiTrMode == uiTrDepth); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; const UInt uiZOrder = pcCU->getZorderIdxInCtu() + uiAbsPartIdx; if (rTu.ProcessComponentSection(compID)) { const TComRectangle &tuRect=rTu.getRect(compID); //===== copy transform coefficients ===== const UInt uiNumCoeff = tuRect.width * tuRect.height; TCoeff* pcCoeffDst = m_ppcQTTempCoeff[compID] [ uiQTLayer ] + rTu.getCoefficientOffset(compID); TCoeff* pcCoeffSrc = m_pcQTTempTUCoeff[compID]; ::memcpy( pcCoeffDst, pcCoeffSrc, sizeof( TCoeff ) * uiNumCoeff ); #if ADAPTIVE_QP_SELECTION TCoeff* pcArlCoeffDst = m_ppcQTTempArlCoeff[compID] [ uiQTLayer ] + rTu.getCoefficientOffset(compID); TCoeff* pcArlCoeffSrc = m_ppcQTTempTUArlCoeff[compID]; ::memcpy( pcArlCoeffDst, pcArlCoeffSrc, sizeof( TCoeff ) * uiNumCoeff ); #endif //===== copy reconstruction ===== m_pcQTTempTransformSkipTComYuv.copyPartToPartComponent( compID, &m_pcQTTempTComYuv[ uiQTLayer ], uiAbsPartIdx, tuRect.width, tuRect.height ); Pel* piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), uiZOrder ); UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride (compID); Pel* piRecQt = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx ); UInt uiRecQtStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride (compID); UInt uiWidth = tuRect.width; UInt uiHeight = tuRect.height; Pel* pRecQt = piRecQt; Pel* pRecIPred = piRecIPred; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pRecIPred[ uiX ] = pRecQt [ uiX ]; } pRecQt += uiRecQtStride; pRecIPred += uiRecIPredStride; } } } } Void TEncSearch::xStoreCrossComponentPredictionResult( Pel *pResiDst, const Pel *pResiSrc, TComTU &rTu, const Int xOffset, const Int yOffset, const Int strideDst, const Int strideSrc ) { const Pel *pSrc = pResiSrc + yOffset * strideSrc + xOffset; Pel *pDst = pResiDst + yOffset * strideDst + xOffset; for( Int y = 0; y < rTu.getRect( COMPONENT_Y ).height; y++ ) { ::memcpy( pDst, pSrc, sizeof(Pel) * rTu.getRect( COMPONENT_Y ).width ); pDst += strideDst; pSrc += strideSrc; } } SChar TEncSearch::xCalcCrossComponentPredictionAlpha( TComTU &rTu, const ComponentID compID, const Pel* piResiL, const Pel* piResiC, const Int width, const Int height, const Int strideL, const Int strideC ) { const Pel *pResiL = piResiL; const Pel *pResiC = piResiC; TComDataCU *pCU = rTu.getCU(); const Int absPartIdx = rTu.GetAbsPartIdxTU( compID ); const Int diffBitDepth = pCU->getSlice()->getSPS()->getDifferentialLumaChromaBitDepth(); SChar alpha = 0; Int SSxy = 0; Int SSxx = 0; for( UInt uiY = 0; uiY < height; uiY++ ) { for( UInt uiX = 0; uiX < width; uiX++ ) { const Pel scaledResiL = rightShift( pResiL[ uiX ], diffBitDepth ); SSxy += ( scaledResiL * pResiC[ uiX ] ); SSxx += ( scaledResiL * scaledResiL ); } pResiL += strideL; pResiC += strideC; } if( SSxx != 0 ) { Double dAlpha = SSxy / Double( SSxx ); alpha = SChar(Clip3(-16, 16, (Int)(dAlpha * 16))); static const SChar alphaQuant[17] = {0, 1, 1, 2, 2, 2, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8}; alpha = (alpha < 0) ? -alphaQuant[Int(-alpha)] : alphaQuant[Int(alpha)]; } pCU->setCrossComponentPredictionAlphaPartRange( alpha, compID, absPartIdx, rTu.GetAbsPartIdxNumParts( compID ) ); return alpha; } Void TEncSearch::xRecurIntraChromaCodingQT(TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE], Distortion& ruiDist, TComTU& rTu DEBUG_STRING_FN_DECLARE(sDebug)) { TComDataCU *pcCU = rTu.getCU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const ChromaFormat format = rTu.GetChromaFormat(); UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); const UInt numberValidComponents = getNumberValidComponents(format); if( uiTrMode == uiTrDepth ) { if (!rTu.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) { return; } const UInt uiFullDepth = rTu.GetTransformDepthTotal(); Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip(); checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Cb), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()); if ( m_pcEncCfg->getUseTransformSkipFast() ) { checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()); if (checkTransformSkip) { Int nbLumaSkip = 0; const UInt maxAbsPartIdxSub=uiAbsPartIdx + (rTu.ProcessingAllQuadrants(COMPONENT_Cb)?1:4); for(UInt absPartIdxSub = uiAbsPartIdx; absPartIdxSub < maxAbsPartIdxSub; absPartIdxSub ++) { nbLumaSkip += pcCU->getTransformSkip(absPartIdxSub, COMPONENT_Y); } checkTransformSkip &= (nbLumaSkip > 0); } } for (UInt ch=COMPONENT_Cb; chstore( m_pppcRDSbacCoder[uiFullDepth][CI_QT_TRAFO_ROOT] ); const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height; TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID); const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID); do { const UInt subTUAbsPartIdx = TUIterator.GetAbsPartIdxTU(compID); Double dSingleCost = MAX_DOUBLE; Int bestModeId = 0; Distortion singleDistC = 0; UInt singleCbfC = 0; Distortion singleDistCTmp = 0; Double singleCostTmp = 0; UInt singleCbfCTmp = 0; SChar bestCrossCPredictionAlpha = 0; Int bestTransformSkipMode = 0; const Bool checkCrossComponentPrediction = (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) == DM_CHROMA_IDX) && pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && (pcCU->getCbf(subTUAbsPartIdx, COMPONENT_Y, uiTrDepth) != 0); const Int crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1; const Int transformSkipModesToTest = checkTransformSkip ? 2 : 1; const Int totalModesToTest = crossCPredictionModesToTest * transformSkipModesToTest; Int currModeId = 0; Int default0Save1Load2 = 0; for(Int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++) { for(Int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++) { pcCU->setCrossComponentPredictionAlphaPartRange(0, compID, subTUAbsPartIdx, partIdxesPerSubTU); DEBUG_STRING_NEW(sDebugMode) pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU ); currModeId++; const Bool isOneMode = (totalModesToTest == 1); const Bool isLastMode = (currModeId == totalModesToTest); // currModeId is indexed from 1 if (isOneMode) { default0Save1Load2 = 0; } else if (!isOneMode && (transformSkipModeId == 0) && (crossCPredictionModeId == 0)) { default0Save1Load2 = 1; //save prediction on first mode } else { default0Save1Load2 = 2; //load it on subsequent modes } singleDistCTmp = 0; xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, (crossCPredictionModeId != 0), singleDistCTmp, compID, TUIterator DEBUG_STRING_PASS_INTO(sDebugMode), default0Save1Load2); singleCbfCTmp = pcCU->getCbf( subTUAbsPartIdx, compID, uiTrDepth); if ( ((crossCPredictionModeId == 1) && (pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) == 0)) || ((transformSkipModeId == 1) && (singleCbfCTmp == 0))) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. { singleCostTmp = MAX_DOUBLE; } else if (!isOneMode) { UInt bitsTmp = xGetIntraBitsQTChroma( TUIterator, compID, false ); singleCostTmp = m_pcRdCost->calcRdCost( bitsTmp, singleDistCTmp); } if(singleCostTmp < dSingleCost) { DEBUG_STRING_SWAP(sDebugBestMode, sDebugMode) dSingleCost = singleCostTmp; singleDistC = singleDistCTmp; bestCrossCPredictionAlpha = (crossCPredictionModeId != 0) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : 0; bestTransformSkipMode = transformSkipModeId; bestModeId = currModeId; singleCbfC = singleCbfCTmp; if (!isOneMode && !isLastMode) { xStoreIntraResultQT(compID, TUIterator); m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } } if (!isOneMode && !isLastMode) { m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } } } if(bestModeId < totalModesToTest) { xLoadIntraResultQT(compID, TUIterator); pcCU->setCbfPartRange( singleCbfC << uiTrDepth, compID, subTUAbsPartIdx, partIdxesPerSubTU ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } DEBUG_STRING_APPEND(sDebug, sDebugBestMode) pcCU ->setTransformSkipPartRange ( bestTransformSkipMode, compID, subTUAbsPartIdx, partIdxesPerSubTU ); pcCU ->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha, compID, subTUAbsPartIdx, partIdxesPerSubTU ); ruiDist += singleDistC; } while (TUIterator.nextSection(rTu)); if (splitIntoSubTUs) { offsetSubTUCBFs(rTu, compID); } } } else { UInt uiSplitCbf[MAX_NUM_COMPONENT] = {0,0,0}; TComTURecurse tuRecurseChild(rTu, false); const UInt uiTrDepthChild = tuRecurseChild.GetTransformDepthRel(); do { DEBUG_STRING_NEW(sChild) xRecurIntraChromaCodingQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, ruiDist, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) ); DEBUG_STRING_APPEND(sDebug, sChild) const UInt uiAbsPartIdxSub=tuRecurseChild.GetAbsPartIdxTU(); for(UInt ch=COMPONENT_Cb; chgetCbf( uiAbsPartIdxSub, ComponentID(ch), uiTrDepthChild ); } } while ( tuRecurseChild.nextSection(rTu) ); UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts(); for(UInt ch=COMPONENT_Cb; chgetCbf( compID ); for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ ) { pBase[ uiAbsPartIdx + uiOffs ] |= flag; } } } } } Void TEncSearch::xSetIntraResultChromaQT(TComYuv* pcRecoYuv, TComTU &rTu) { if (!rTu.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) { return; } TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiTrDepth = rTu.GetTransformDepthRel(); UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); if( uiTrMode == uiTrDepth ) { UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; //===== copy transform coefficients ===== const TComRectangle &tuRectCb=rTu.getRect(COMPONENT_Cb); UInt uiNumCoeffC = tuRectCb.width*tuRectCb.height;//( pcCU->getSlice()->getSPS()->getMaxCUWidth() * pcCU->getSlice()->getSPS()->getMaxCUHeight() ) >> ( uiFullDepth << 1 ); const UInt offset = rTu.getCoefficientOffset(COMPONENT_Cb); const UInt numberValidComponents = getNumberValidComponents(rTu.GetChromaFormat()); for (UInt ch=COMPONENT_Cb; chgetCoeff(component) + offset;//(uiNumCoeffIncC*uiAbsPartIdx); ::memcpy( dest, src, sizeof(TCoeff)*uiNumCoeffC ); #if ADAPTIVE_QP_SELECTION TCoeff* pcArlCoeffSrc = m_ppcQTTempArlCoeff[component][ uiQTLayer ] + offset;//( uiNumCoeffIncC * uiAbsPartIdx ); TCoeff* pcArlCoeffDst = pcCU->getArlCoeff(component) + offset;//( uiNumCoeffIncC * uiAbsPartIdx ); ::memcpy( pcArlCoeffDst, pcArlCoeffSrc, sizeof( TCoeff ) * uiNumCoeffC ); #endif } //===== copy reconstruction ===== m_pcQTTempTComYuv[ uiQTLayer ].copyPartToPartComponent( COMPONENT_Cb, pcRecoYuv, uiAbsPartIdx, tuRectCb.width, tuRectCb.height ); m_pcQTTempTComYuv[ uiQTLayer ].copyPartToPartComponent( COMPONENT_Cr, pcRecoYuv, uiAbsPartIdx, tuRectCb.width, tuRectCb.height ); } else { TComTURecurse tuRecurseChild(rTu, false); do { xSetIntraResultChromaQT( pcRecoYuv, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } } Void TEncSearch::estIntraPredLumaQT(TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE] DEBUG_STRING_FN_DECLARE(sDebug)) { const UInt uiDepth = pcCU->getDepth(0); const UInt uiInitTrDepth = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; const UInt uiNumPU = 1<<(2*uiInitTrDepth); const UInt uiQNumParts = pcCU->getTotalNumPart() >> 2; const UInt uiWidthBit = pcCU->getIntraSizeIdx(0); const ChromaFormat chFmt = pcCU->getPic()->getChromaFormat(); const UInt numberValidComponents = getNumberValidComponents(chFmt); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const TComPPS &pps = *(pcCU->getSlice()->getPPS()); Distortion uiOverallDistY = 0; UInt CandNum; Double CandCostList[ FAST_UDI_MAX_RDMODE_NUM ]; Pel resiLumaPU[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE]; Bool bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES]; for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++) { bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise } bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate()); // Lambda calculation at equivalent Qp of 4 is recommended because at that Qp, the quantisation divisor is 1. #if FULL_NBIT const Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ? sqrt(0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12) / 3.0))) : m_pcRdCost->getSqrtLambda(); #else const Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ? sqrt(0.57 * pow(2.0, ((LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12 - 6 * (sps.getBitDepth(CHANNEL_TYPE_LUMA) - 8)) / 3.0))) : m_pcRdCost->getSqrtLambda(); #endif //===== set QP and clear Cbf ===== if ( pps.getUseDQP() == true) { pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth ); } else { pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth ); } //===== loop over partitions ===== TComTURecurse tuRecurseCU(pcCU, 0); TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT); do { const UInt uiPartOffset=tuRecurseWithPU.GetAbsPartIdxTU(); // for( UInt uiPU = 0, uiPartOffset=0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts ) //{ //===== init pattern for luma prediction ===== DEBUG_STRING_NEW(sTemp2) //===== determine set of modes to be tested (using prediction signal only) ===== Int numModesAvailable = 35; //total number of Intra modes UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM]; Int numModesForFullRD = m_pcEncCfg->getFastUDIUseMPMEnabled()?g_aucIntraModeNumFast_UseMPM[ uiWidthBit ] : g_aucIntraModeNumFast_NotUseMPM[ uiWidthBit ]; // this should always be true assert (tuRecurseWithPU.ProcessComponentSection(COMPONENT_Y)); initIntraPatternChType( tuRecurseWithPU, COMPONENT_Y, true DEBUG_STRING_PASS_INTO(sTemp2) ); Bool doFastSearch = (numModesForFullRD != numModesAvailable); if (doFastSearch) { assert(numModesForFullRD < numModesAvailable); for( Int i=0; i < numModesForFullRD; i++ ) { CandCostList[ i ] = MAX_DOUBLE; } CandNum = 0; const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y); const UInt uiAbsPartIdx=tuRecurseWithPU.GetAbsPartIdxTU(); Pel* piOrg = pcOrgYuv ->getAddr( COMPONENT_Y, uiAbsPartIdx ); Pel* piPred = pcPredYuv->getAddr( COMPONENT_Y, uiAbsPartIdx ); UInt uiStride = pcPredYuv->getStride( COMPONENT_Y ); DistParam distParam; const Bool bUseHadamard=pcCU->getCUTransquantBypass(0) == 0; m_pcRdCost->setDistParam(distParam, sps.getBitDepth(CHANNEL_TYPE_LUMA), piOrg, uiStride, piPred, uiStride, puRect.width, puRect.height, bUseHadamard); distParam.bApplyWeight = false; for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) { UInt uiMode = modeIdx; Distortion uiSad = 0; const Bool bUseFilter=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, uiMode, puRect.width, puRect.height, chFmt, sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag()); predIntraAng( COMPONENT_Y, uiMode, piOrg, uiStride, piPred, uiStride, tuRecurseWithPU, bUseFilter, TComPrediction::UseDPCMForFirstPassIntraEstimation(tuRecurseWithPU, uiMode) ); // use hadamard transform here uiSad+=distParam.DistFunc(&distParam); UInt iModeBits = 0; // NB xModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated. iModeBits+=xModeBitsIntra( pcCU, uiMode, uiPartOffset, uiDepth, CHANNEL_TYPE_LUMA ); Double cost = (Double)uiSad + (Double)iModeBits * sqrtLambdaForFirstPass; #if DEBUG_INTRA_SEARCH_COSTS std::cout << "1st pass mode " << uiMode << " SAD = " << uiSad << ", mode bits = " << iModeBits << ", cost = " << cost << "\n"; #endif CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList ); } (Void)CandNum; // Avoid compiler warning: CandNum is never used if (m_pcEncCfg->getFastUDIUseMPMEnabled()) { Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1}; Int iMode = -1; pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode ); const Int numCand = ( iMode >= 0 ) ? iMode : Int(NUM_MOST_PROBABLE_MODES); for( Int j=0; j < numCand; j++) { Bool mostProbableModeIncluded = false; Int mostProbableMode = uiPreds[j]; for( Int i=0; i < numModesForFullRD; i++) { mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); } if (!mostProbableModeIncluded) { uiRdModeList[numModesForFullRD++] = mostProbableMode; } } } } else { for( Int i=0; i < numModesForFullRD; i++) { uiRdModeList[i] = i; } } //===== check modes (using r-d costs) ===== #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiSecondBestMode = MAX_UINT; Double dSecondBestPUCost = MAX_DOUBLE; #endif DEBUG_STRING_NEW(sPU) UInt uiBestPUMode = 0; Distortion uiBestPUDistY = 0; Double dBestPUCost = MAX_DOUBLE; #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST UInt max=numModesForFullRD; if (DebugOptionList::ForceLumaMode.isSet()) { max=0; // we are forcing a direction, so don't bother with mode check } for ( UInt uiMode = 0; uiMode < max; uiMode++) #else for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) #endif { // set luma prediction mode UInt uiOrgMode = uiRdModeList[uiMode]; pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); DEBUG_STRING_NEW(sMode) // set context models m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); // determine residual for partition Distortion uiPUDistY = 0; Double dPUCost = 0.0; #if HHI_RQT_INTRA_SPEEDUP xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, true, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #else xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #endif #if DEBUG_INTRA_SEARCH_COSTS std::cout << "2nd pass [luma,chroma] mode [" << Int(pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiPartOffset)) << "," << Int(pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiPartOffset)) << "] cost = " << dPUCost << "\n"; #endif // check r-d cost if( dPUCost < dBestPUCost ) { DEBUG_STRING_SWAP(sPU, sMode) #if HHI_RQT_INTRA_SPEEDUP_MOD uiSecondBestMode = uiBestPUMode; dSecondBestPUCost = dBestPUCost; #endif uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; dBestPUCost = dPUCost; xSetIntraResultLumaQT( pcRecoYuv, tuRecurseWithPU ); if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0; const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE ); } } } UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip(compID) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } } #if HHI_RQT_INTRA_SPEEDUP_MOD else if( dPUCost < dSecondBestPUCost ) { uiSecondBestMode = uiOrgMode; dSecondBestPUCost = dPUCost; } #endif } // Mode loop #if HHI_RQT_INTRA_SPEEDUP #if HHI_RQT_INTRA_SPEEDUP_MOD for( UInt ui =0; ui < 2; ++ui ) #endif { #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiOrgMode = ui ? uiSecondBestMode : uiBestPUMode; if( uiOrgMode == MAX_UINT ) { break; } #else UInt uiOrgMode = uiBestPUMode; #endif #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (DebugOptionList::ForceLumaMode.isSet()) { uiOrgMode = DebugOptionList::ForceLumaMode.getInt(); } #endif pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); DEBUG_STRING_NEW(sModeTree) // set context models m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); // determine residual for partition Distortion uiPUDistY = 0; Double dPUCost = 0.0; xRecurIntraCodingLumaQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, false, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sModeTree)); // check r-d cost if( dPUCost < dBestPUCost ) { DEBUG_STRING_SWAP(sPU, sModeTree) uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; dBestPUCost = dPUCost; xSetIntraResultLumaQT( pcRecoYuv, tuRecurseWithPU ); if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()) { const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0; const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE ); } } } const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip(compID) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } } } // Mode loop #endif DEBUG_STRING_APPEND(sDebug, sPU) //--- update overall distortion --- uiOverallDistY += uiBestPUDistY; //--- update transform index and cbf --- const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( pcCU->getTransformIdx() + uiPartOffset, m_puhQTTempTrIdx, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( pcCU->getCbf( compID ) + uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getTransformSkip( compID ) + uiPartOffset, m_puhQTTempTransformSkipFlag[compID ], uiQPartNum * sizeof( UChar ) ); } //--- set reconstruction for next intra prediction blocks --- if( !tuRecurseWithPU.IsLastSection() ) { const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y); const UInt uiCompWidth = puRect.width; const UInt uiCompHeight = puRect.height; const UInt uiZOrder = pcCU->getZorderIdxInCtu() + uiPartOffset; Pel* piDes = pcCU->getPic()->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), uiZOrder ); const UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride( COMPONENT_Y); const Pel* piSrc = pcRecoYuv->getAddr( COMPONENT_Y, uiPartOffset ); const UInt uiSrcStride = pcRecoYuv->getStride( COMPONENT_Y); for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ) { for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ) { piDes[ uiX ] = piSrc[ uiX ]; } } } //=== update PU data ==== pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth ); } while (tuRecurseWithPU.nextSection(tuRecurseCU)); if( uiNumPU > 1 ) { // set Cbf for all blocks UInt uiCombCbfY = 0; UInt uiCombCbfU = 0; UInt uiCombCbfV = 0; UInt uiPartIdx = 0; for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ) { uiCombCbfY |= pcCU->getCbf( uiPartIdx, COMPONENT_Y, 1 ); uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 ); uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 ); } for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ) { pcCU->getCbf( COMPONENT_Y )[ uiOffs ] |= uiCombCbfY; pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU; pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV; } } //===== reset context models ===== m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); //===== set distortion (rate and r-d costs are determined later) ===== pcCU->getTotalDistortion() = uiOverallDistY; } Void TEncSearch::estIntraPredChromaQT(TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE] DEBUG_STRING_FN_DECLARE(sDebug)) { const UInt uiInitTrDepth = pcCU->getPartitionSize(0) != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? 1 : 0; TComTURecurse tuRecurseCU(pcCU, 0); TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT); const UInt uiQNumParts = tuRecurseWithPU.GetAbsPartIdxNumParts(); const UInt uiDepthCU=tuRecurseWithPU.getCUDepth(); const UInt numberValidComponents = pcCU->getPic()->getNumberValidComponents(); do { UInt uiBestMode = 0; Distortion uiBestDist = 0; Double dBestCost = MAX_DOUBLE; //----- init mode list ----- if (tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) { UInt uiModeList[FAST_UDI_MAX_RDMODE_NUM]; const UInt uiQPartNum = uiQNumParts; const UInt uiPartOffset = tuRecurseWithPU.GetAbsPartIdxTU(); { UInt uiMinMode = 0; UInt uiMaxMode = NUM_CHROMA_MODE; //----- check chroma modes ----- pcCU->getAllowedChromaDir( uiPartOffset, uiModeList ); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (DebugOptionList::ForceChromaMode.isSet()) { uiMinMode=DebugOptionList::ForceChromaMode.getInt(); if (uiModeList[uiMinMode]==34) { uiMinMode=4; // if the fixed mode has been renumbered because DM_CHROMA covers it, use DM_CHROMA. } uiMaxMode=uiMinMode+1; } #endif DEBUG_STRING_NEW(sPU) for( UInt uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++ ) { //----- restore context models ----- m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] ); DEBUG_STRING_NEW(sMode) //----- chroma coding ----- Distortion uiDist = 0; pcCU->setIntraDirSubParts ( CHANNEL_TYPE_CHROMA, uiModeList[uiMode], uiPartOffset, uiDepthCU+uiInitTrDepth ); xRecurIntraChromaCodingQT ( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, uiDist, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); if( pcCU->getSlice()->getPPS()->getUseTransformSkip() ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] ); } UInt uiBits = xGetIntraBitsQT( tuRecurseWithPU, false, true, false ); Double dCost = m_pcRdCost->calcRdCost( uiBits, uiDist ); //----- compare ----- if( dCost < dBestCost ) { DEBUG_STRING_SWAP(sPU, sMode); dBestCost = dCost; uiBestDist = uiDist; uiBestMode = uiModeList[uiMode]; xSetIntraResultChromaQT( pcRecoYuv, tuRecurseWithPU ); for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++) { const ComponentID compID = ComponentID(componentIndex); ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_phQTTempCrossComponentPredictionAlpha[compID], pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, uiQPartNum * sizeof( SChar ) ); } } } DEBUG_STRING_APPEND(sDebug, sPU) //----- set data ----- for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++) { const ComponentID compID = ComponentID(componentIndex); ::memcpy( pcCU->getCbf( compID )+uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getTransformSkip( compID )+uiPartOffset, m_puhQTTempTransformSkipFlag[compID], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, m_phQTTempCrossComponentPredictionAlpha[compID], uiQPartNum * sizeof( SChar ) ); } } if( ! tuRecurseWithPU.IsLastSection() ) { for (UInt ch=COMPONENT_Cb; chgetZorderIdxInCtu() + tuRecurseWithPU.GetAbsPartIdxTU(); Pel* piDes = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), uiZOrder ); const UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride( compID); const Pel* piSrc = pcRecoYuv->getAddr( compID, uiPartOffset ); const UInt uiSrcStride = pcRecoYuv->getStride( compID); for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ) { for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ) { piDes[ uiX ] = piSrc[ uiX ]; } } } } pcCU->setIntraDirSubParts( CHANNEL_TYPE_CHROMA, uiBestMode, uiPartOffset, uiDepthCU+uiInitTrDepth ); pcCU->getTotalDistortion () += uiBestDist; } } while (tuRecurseWithPU.nextSection(tuRecurseCU)); //----- restore context models ----- if( uiInitTrDepth != 0 ) { // set Cbf for all blocks UInt uiCombCbfU = 0; UInt uiCombCbfV = 0; UInt uiPartIdx = 0; for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ) { uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 ); uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 ); } for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ) { pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU; pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV; } } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] ); } /** Function for encoding and reconstructing luma/chroma samples of a PCM mode CU. * \param pcCU pointer to current CU * \param uiAbsPartIdx part index * \param pOrg pointer to original sample arrays * \param pPCM pointer to PCM code arrays * \param pPred pointer to prediction signal arrays * \param pResi pointer to residual signal arrays * \param pReco pointer to reconstructed sample arrays * \param uiStride stride of the original/prediction/residual sample arrays * \param uiWidth block width * \param uiHeight block height * \param compID texture component type */ Void TEncSearch::xEncPCM (TComDataCU* pcCU, UInt uiAbsPartIdx, Pel* pOrg, Pel* pPCM, Pel* pPred, Pel* pResi, Pel* pReco, UInt uiStride, UInt uiWidth, UInt uiHeight, const ComponentID compID ) { const UInt uiReconStride = pcCU->getPic()->getPicYuvRec()->getStride(compID); const UInt uiPCMBitDepth = pcCU->getSlice()->getSPS()->getPCMBitDepth(toChannelType(compID)); const Int channelBitDepth = pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID)); Pel* pRecoPic = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiAbsPartIdx); const Int pcmShiftRight=(channelBitDepth - Int(uiPCMBitDepth)); assert(pcmShiftRight >= 0); for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { // Reset pred and residual pPred[uiX] = 0; pResi[uiX] = 0; // Encode pPCM[uiX] = (pOrg[uiX]>>pcmShiftRight); // Reconstruction pReco [uiX] = (pPCM[uiX]<<(pcmShiftRight)); pRecoPic[uiX] = pReco[uiX]; } pPred += uiStride; pResi += uiStride; pPCM += uiWidth; pOrg += uiStride; pReco += uiStride; pRecoPic += uiReconStride; } } //! Function for PCM mode estimation. Void TEncSearch::IPCMSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv ) { UInt uiDepth = pcCU->getDepth(0); const Distortion uiDistortion = 0; UInt uiBits; Double dCost; for (UInt ch=0; ch < pcCU->getPic()->getNumberValidComponents(); ch++) { const ComponentID compID = ComponentID(ch); const UInt width = pcCU->getWidth(0) >> pcCU->getPic()->getComponentScaleX(compID); const UInt height = pcCU->getHeight(0) >> pcCU->getPic()->getComponentScaleY(compID); const UInt stride = pcPredYuv->getStride(compID); Pel * pOrig = pcOrgYuv->getAddr (compID, 0, width); Pel * pResi = pcResiYuv->getAddr(compID, 0, width); Pel * pPred = pcPredYuv->getAddr(compID, 0, width); Pel * pReco = pcRecoYuv->getAddr(compID, 0, width); Pel * pPCM = pcCU->getPCMSample (compID); xEncPCM ( pcCU, 0, pOrig, pPCM, pPred, pResi, pReco, stride, width, height, compID ); } m_pcEntropyCoder->resetBits(); xEncIntraHeader ( pcCU, uiDepth, 0, true, false); uiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); dCost = m_pcRdCost->calcRdCost( uiBits, uiDistortion ); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); pcCU->getTotalBits() = uiBits; pcCU->getTotalCost() = dCost; pcCU->getTotalDistortion() = uiDistortion; pcCU->copyToPic(uiDepth); } Void TEncSearch::xGetInterPredictionError( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPartIdx, Distortion& ruiErr, Bool /*bHadamard*/ ) { motionCompensation( pcCU, &m_tmpYuvPred, REF_PIC_LIST_X, iPartIdx ); UInt uiAbsPartIdx = 0; Int iWidth = 0; Int iHeight = 0; pcCU->getPartIndexAndSize( iPartIdx, uiAbsPartIdx, iWidth, iHeight ); DistParam cDistParam; cDistParam.bApplyWeight = false; m_pcRdCost->setDistParam( cDistParam, pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA), pcYuvOrg->getAddr( COMPONENT_Y, uiAbsPartIdx ), pcYuvOrg->getStride(COMPONENT_Y), m_tmpYuvPred .getAddr( COMPONENT_Y, uiAbsPartIdx ), m_tmpYuvPred.getStride(COMPONENT_Y), iWidth, iHeight, m_pcEncCfg->getUseHADME() && (pcCU->getCUTransquantBypass(iPartIdx) == 0) ); ruiErr = cDistParam.DistFunc( &cDistParam ); } //! estimation of best merge coding Void TEncSearch::xMergeEstimation( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPUIdx, UInt& uiInterDir, TComMvField* pacMvField, UInt& uiMergeIndex, Distortion& ruiCost, TComMvField* cMvFieldNeighbours, UChar* uhInterDirNeighbours, Int& numValidMergeCand ) { UInt uiAbsPartIdx = 0; Int iWidth = 0; Int iHeight = 0; pcCU->getPartIndexAndSize( iPUIdx, uiAbsPartIdx, iWidth, iHeight ); UInt uiDepth = pcCU->getDepth( uiAbsPartIdx ); PartSize partSize = pcCU->getPartitionSize( 0 ); if ( pcCU->getSlice()->getPPS()->getLog2ParallelMergeLevelMinus2() && partSize != SIZE_2Nx2N && pcCU->getWidth( 0 ) <= 8 ) { if ( iPUIdx == 0 ) { pcCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uiDepth ); // temporarily set #if MCTS_ENC_CHECK UInt numSpatialMergeCandidates = 0; pcCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates ); if (m_pcEncCfg->getTMCTSSEITileConstraint() && pcCU->isLastColumnCTUInTile()) { numValidMergeCand = numSpatialMergeCandidates; } #else pcCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand ); #endif pcCU->setPartSizeSubParts( partSize, 0, uiDepth ); // restore } } else { #if MCTS_ENC_CHECK UInt numSpatialMergeCandidates = 0; pcCU->getInterMergeCandidates( uiAbsPartIdx, iPUIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates ); if (m_pcEncCfg->getTMCTSSEITileConstraint() && pcCU->isLastColumnCTUInTile()) { numValidMergeCand = numSpatialMergeCandidates; } #else pcCU->getInterMergeCandidates( uiAbsPartIdx, iPUIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand ); #endif } xRestrictBipredMergeCand( pcCU, iPUIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand ); ruiCost = std::numeric_limits::max(); for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand ) { Distortion uiCostCand = std::numeric_limits::max(); UInt uiBitsCand = 0; PartSize ePartSize = pcCU->getPartitionSize( 0 ); pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], ePartSize, uiAbsPartIdx, 0, iPUIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], ePartSize, uiAbsPartIdx, 0, iPUIdx ); xGetInterPredictionError( pcCU, pcYuvOrg, iPUIdx, uiCostCand, m_pcEncCfg->getUseHADME() ); uiBitsCand = uiMergeCand + 1; if (uiMergeCand == m_pcEncCfg->getMaxNumMergeCand() -1) { uiBitsCand--; } uiCostCand = uiCostCand + m_pcRdCost->getCost( uiBitsCand ); if ( uiCostCand < ruiCost ) { ruiCost = uiCostCand; pacMvField[0] = cMvFieldNeighbours[0 + 2*uiMergeCand]; pacMvField[1] = cMvFieldNeighbours[1 + 2*uiMergeCand]; uiInterDir = uhInterDirNeighbours[uiMergeCand]; uiMergeIndex = uiMergeCand; } } } /** convert bi-pred merge candidates to uni-pred * \param pcCU * \param puIdx * \param mvFieldNeighbours * \param interDirNeighbours * \param numValidMergeCand * \returns Void */ Void TEncSearch::xRestrictBipredMergeCand( TComDataCU* pcCU, UInt puIdx, TComMvField* mvFieldNeighbours, UChar* interDirNeighbours, Int numValidMergeCand ) { if ( pcCU->isBipredRestriction(puIdx) ) { for( UInt mergeCand = 0; mergeCand < numValidMergeCand; ++mergeCand ) { if ( interDirNeighbours[mergeCand] == 3 ) { interDirNeighbours[mergeCand] = 1; mvFieldNeighbours[(mergeCand << 1) + 1].setMvField(TComMv(0,0), -1); } } } } //! search of the best candidate for inter prediction #if AMP_MRG Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseRes, Bool bUseMRG ) #else Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Bool bUseRes ) #endif { for(UInt i=0; iclear(); if ( !bUseRes ) { pcResiYuv->clear(); } pcRecoYuv->clear(); TComMv cMvSrchRngLT; TComMv cMvSrchRngRB; TComMv cMvZero; TComMv TempMv; //kolya TComMv cMv[2]; TComMv cMvBi[2]; TComMv cMvTemp[2][33]; Int iNumPart = pcCU->getNumPartitions(); Int iNumPredDir = pcCU->getSlice()->isInterP() ? 1 : 2; TComMv cMvPred[2][33]; TComMv cMvPredBi[2][33]; Int aaiMvpIdxBi[2][33]; Int aaiMvpIdx[2][33]; Int aaiMvpNum[2][33]; AMVPInfo aacAMVPInfo[2][33]; Int iRefIdx[2]={0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage. Int iRefIdxBi[2]; UInt uiPartAddr; Int iRoiWidth, iRoiHeight; UInt uiMbBits[3] = {1, 1, 0}; UInt uiLastMode = 0; Int iRefStart, iRefEnd; PartSize ePartSize = pcCU->getPartitionSize( 0 ); Int bestBiPRefIdxL1 = 0; Int bestBiPMvpL1 = 0; Distortion biPDistTemp = std::numeric_limits::max(); TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS]; Int numValidMergeCand = 0 ; for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ ) { Distortion uiCost[2] = { std::numeric_limits::max(), std::numeric_limits::max() }; Distortion uiCostBi = std::numeric_limits::max(); Distortion uiCostTemp; UInt uiBits[3]; UInt uiBitsTemp; Distortion bestBiPDist = std::numeric_limits::max(); Distortion uiCostTempL0[MAX_NUM_REF]; for (Int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++) { uiCostTempL0[iNumRef] = std::numeric_limits::max(); } UInt uiBitsTempL0[MAX_NUM_REF]; TComMv mvValidList1; Int refIdxValidList1 = 0; UInt bitsValidList1 = MAX_UINT; Distortion costValidList1 = std::numeric_limits::max(); xGetBlkBits( ePartSize, pcCU->getSlice()->isInterP(), iPartIdx, uiLastMode, uiMbBits); pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight ); #if AMP_MRG Bool bTestNormalMC = true; if ( bUseMRG && pcCU->getWidth( 0 ) > 8 && iNumPart == 2 ) { bTestNormalMC = false; } if (bTestNormalMC) { #endif // Uni-directional prediction for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ ) { RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( Int iRefIdxTemp = 0; iRefIdxTemp < pcCU->getSlice()->getNumRefIdx(eRefPicList); iRefIdxTemp++ ) { uiBitsTemp = uiMbBits[iRefList]; if ( pcCU->getSlice()->getNumRefIdx(eRefPicList) > 1 ) { uiBitsTemp += iRefIdxTemp+1; if ( iRefIdxTemp == pcCU->getSlice()->getNumRefIdx(eRefPicList)-1 ) { uiBitsTemp--; } } xEstimateMvPredAMVP( pcCU, pcOrgYuv, iPartIdx, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], false, &biPDistTemp); aaiMvpIdx[iRefList][iRefIdxTemp] = pcCU->getMVPIdx(eRefPicList, uiPartAddr); aaiMvpNum[iRefList][iRefIdxTemp] = pcCU->getMVPNum(eRefPicList, uiPartAddr); if(pcCU->getSlice()->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist) { bestBiPDist = biPDistTemp; bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp]; bestBiPRefIdxL1 = iRefIdxTemp; } uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS]; if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 ) // list 1 { if ( pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 ) { cMvTemp[1][iRefIdxTemp] = cMvTemp[0][pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )]; uiCostTemp = uiCostTempL0[pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )]; /*first subtract the bit-rate part of the cost of the other list*/ uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp )] ); /*correct the bit-rate part of the current ref*/ m_pcRdCost->setPredictor ( cMvPred[iRefList][iRefIdxTemp] ); uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer() ); /*calculate the correct cost*/ uiCostTemp += m_pcRdCost->getCost( uiBitsTemp ); } else { xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp ); } } else { xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp ); } xCopyAMVPInfo(pcCU->getCUMvField(eRefPicList)->getAMVPInfo(), &aacAMVPInfo[iRefList][iRefIdxTemp]); // must always be done ( also when AMVP_MODE = AM_NONE ) xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp); if ( iRefList == 0 ) { uiCostTempL0[iRefIdxTemp] = uiCostTemp; uiBitsTempL0[iRefIdxTemp] = uiBitsTemp; } if ( uiCostTemp < uiCost[iRefList] ) { uiCost[iRefList] = uiCostTemp; uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction // set motion cMv[iRefList] = cMvTemp[iRefList][iRefIdxTemp]; iRefIdx[iRefList] = iRefIdxTemp; } if ( iRefList == 1 && uiCostTemp < costValidList1 && pcCU->getSlice()->getList1IdxToList0Idx( iRefIdxTemp ) < 0 ) { costValidList1 = uiCostTemp; bitsValidList1 = uiBitsTemp; // set motion mvValidList1 = cMvTemp[iRefList][iRefIdxTemp]; refIdxValidList1 = iRefIdxTemp; } } } // Bi-predictive Motion estimation if ( (pcCU->getSlice()->isInterB()) && (pcCU->isBipredRestriction(iPartIdx) == false) ) { cMvBi[0] = cMv[0]; cMvBi[1] = cMv[1]; iRefIdxBi[0] = iRefIdx[0]; iRefIdxBi[1] = iRefIdx[1]; ::memcpy(cMvPredBi, cMvPred, sizeof(cMvPred)); ::memcpy(aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx)); UInt uiMotBits[2]; if(pcCU->getSlice()->getMvdL1ZeroFlag()) { xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo()); pcCU->setMVPIdxSubParts( bestBiPMvpL1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1; cMvPredBi[1][bestBiPRefIdxL1] = pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo()->m_acMvCand[bestBiPMvpL1]; cMvBi[1] = cMvPredBi[1][bestBiPRefIdxL1]; iRefIdxBi[1] = bestBiPRefIdxL1; pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMv( cMvBi[1], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllRefIdx( iRefIdxBi[1], ePartSize, uiPartAddr, 0, iPartIdx ); TComYuv* pcYuvPred = &m_acYuvPred[REF_PIC_LIST_1]; motionCompensation( pcCU, pcYuvPred, REF_PIC_LIST_1, iPartIdx ); uiMotBits[0] = uiBits[0] - uiMbBits[0]; uiMotBits[1] = uiMbBits[1]; if ( pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1) > 1 ) { uiMotBits[1] += bestBiPRefIdxL1+1; if ( bestBiPRefIdxL1 == pcCU->getSlice()->getNumRefIdx(REF_PIC_LIST_1)-1 ) { uiMotBits[1]--; } } uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS]; uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1]; cMvTemp[1][bestBiPRefIdxL1] = cMvBi[1]; } else { uiMotBits[0] = uiBits[0] - uiMbBits[0]; uiMotBits[1] = uiBits[1] - uiMbBits[1]; uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1]; } // 4-times iteration (default) Int iNumIter = 4; // fast encoder setting: only one iteration if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || pcCU->getSlice()->getMvdL1ZeroFlag() ) { iNumIter = 1; } for ( Int iIter = 0; iIter < iNumIter; iIter++ ) { Int iRefList = iIter % 2; if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 ) { if( uiCost[0] <= uiCost[1] ) { iRefList = 1; } else { iRefList = 0; } } else if ( iIter == 0 ) { iRefList = 0; } if ( iIter == 0 && !pcCU->getSlice()->getMvdL1ZeroFlag()) { pcCU->getCUMvField(RefPicList(1-iRefList))->setAllMv( cMv[1-iRefList], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(RefPicList(1-iRefList))->setAllRefIdx( iRefIdx[1-iRefList], ePartSize, uiPartAddr, 0, iPartIdx ); TComYuv* pcYuvPred = &m_acYuvPred[1-iRefList]; motionCompensation ( pcCU, pcYuvPred, RefPicList(1-iRefList), iPartIdx ); } RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); if(pcCU->getSlice()->getMvdL1ZeroFlag()) { iRefList = 0; eRefPicList = REF_PIC_LIST_0; } Bool bChanged = false; iRefStart = 0; iRefEnd = pcCU->getSlice()->getNumRefIdx(eRefPicList)-1; for ( Int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ ) { uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList]; if ( pcCU->getSlice()->getNumRefIdx(eRefPicList) > 1 ) { uiBitsTemp += iRefIdxTemp+1; if ( iRefIdxTemp == pcCU->getSlice()->getNumRefIdx(eRefPicList)-1 ) { uiBitsTemp--; } } uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS]; // call ME xMotionEstimation ( pcCU, pcOrgYuv, iPartIdx, eRefPicList, &cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, true ); xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], pcCU->getCUMvField(eRefPicList)->getAMVPInfo()); xCheckBestMVP(pcCU, eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp); if ( uiCostTemp < uiCostBi ) { bChanged = true; cMvBi[iRefList] = cMvTemp[iRefList][iRefIdxTemp]; iRefIdxBi[iRefList] = iRefIdxTemp; uiCostBi = uiCostTemp; uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList]; uiBits[2] = uiBitsTemp; if(iNumIter!=1) { // Set motion pcCU->getCUMvField( eRefPicList )->setAllMv( cMvBi[iRefList], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField( eRefPicList )->setAllRefIdx( iRefIdxBi[iRefList], ePartSize, uiPartAddr, 0, iPartIdx ); TComYuv* pcYuvPred = &m_acYuvPred[iRefList]; motionCompensation( pcCU, pcYuvPred, eRefPicList, iPartIdx ); } } } // for loop-iRefIdxTemp if ( !bChanged ) { if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] ) { xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], pcCU->getCUMvField(REF_PIC_LIST_0)->getAMVPInfo()); xCheckBestMVP(pcCU, REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], uiBits[2], uiCostBi); if(!pcCU->getSlice()->getMvdL1ZeroFlag()) { xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], pcCU->getCUMvField(REF_PIC_LIST_1)->getAMVPInfo()); xCheckBestMVP(pcCU, REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], uiBits[2], uiCostBi); } } break; } } // for loop-iter } // if (B_SLICE) #if AMP_MRG } //end if bTestNormalMC #endif // Clear Motion Field pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvField( TComMvField(), ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvField( TComMvField(), ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd ( cMvZero, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd ( cMvZero, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); UInt uiMEBits = 0; // Set Motion Field_ cMv[1] = mvValidList1; iRefIdx[1] = refIdxValidList1; uiBits[1] = bitsValidList1; uiCost[1] = costValidList1; #if AMP_MRG if (bTestNormalMC) { #endif if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) { uiLastMode = 2; pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMv( cMvBi[0], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_0)->setAllRefIdx( iRefIdxBi[0], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMv( cMvBi[1], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllRefIdx( iRefIdxBi[1], ePartSize, uiPartAddr, 0, iPartIdx ); TempMv = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]]; pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd ( TempMv, ePartSize, uiPartAddr, 0, iPartIdx ); TempMv = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]]; pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd ( TempMv, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->setInterDirSubParts( 3, uiPartAddr, iPartIdx, pcCU->getDepth(0) ); pcCU->setMVPIdxSubParts( aaiMvpIdxBi[0][iRefIdxBi[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( aaiMvpNum[0][iRefIdxBi[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPIdxSubParts( aaiMvpIdxBi[1][iRefIdxBi[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( aaiMvpNum[1][iRefIdxBi[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); uiMEBits = uiBits[2]; } else if ( uiCost[0] <= uiCost[1] ) { uiLastMode = 0; pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMv( cMv[0], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_0)->setAllRefIdx( iRefIdx[0], ePartSize, uiPartAddr, 0, iPartIdx ); TempMv = cMv[0] - cMvPred[0][iRefIdx[0]]; pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd ( TempMv, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->setInterDirSubParts( 1, uiPartAddr, iPartIdx, pcCU->getDepth(0) ); pcCU->setMVPIdxSubParts( aaiMvpIdx[0][iRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( aaiMvpNum[0][iRefIdx[0]], REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); uiMEBits = uiBits[0]; } else { uiLastMode = 1; pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMv( cMv[1], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllRefIdx( iRefIdx[1], ePartSize, uiPartAddr, 0, iPartIdx ); TempMv = cMv[1] - cMvPred[1][iRefIdx[1]]; pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd ( TempMv, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->setInterDirSubParts( 2, uiPartAddr, iPartIdx, pcCU->getDepth(0) ); pcCU->setMVPIdxSubParts( aaiMvpIdx[1][iRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( aaiMvpNum[1][iRefIdx[1]], REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); uiMEBits = uiBits[1]; } #if AMP_MRG } // end if bTestNormalMC #endif if ( pcCU->getPartitionSize( uiPartAddr ) != SIZE_2Nx2N ) { UInt uiMRGInterDir = 0; TComMvField cMRGMvField[2]; UInt uiMRGIndex = 0; UInt uiMEInterDir = 0; TComMvField cMEMvField[2]; m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) ); #if AMP_MRG // calculate ME cost Distortion uiMEError = std::numeric_limits::max(); Distortion uiMECost = std::numeric_limits::max(); if (bTestNormalMC) { xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() ); uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits ); } #else // calculate ME cost Distortion uiMEError = std::numeric_limits::max(); xGetInterPredictionError( pcCU, pcOrgYuv, iPartIdx, uiMEError, m_pcEncCfg->getUseHADME() ); Distortion uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits ); #endif // save ME result. uiMEInterDir = pcCU->getInterDir( uiPartAddr ); TComDataCU::getMvField( pcCU, uiPartAddr, REF_PIC_LIST_0, cMEMvField[0] ); TComDataCU::getMvField( pcCU, uiPartAddr, REF_PIC_LIST_1, cMEMvField[1] ); // find Merge result Distortion uiMRGCost = std::numeric_limits::max(); xMergeEstimation( pcCU, pcOrgYuv, iPartIdx, uiMRGInterDir, cMRGMvField, uiMRGIndex, uiMRGCost, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand); if ( uiMRGCost < uiMECost ) { // set Merge result pcCU->setMergeFlagSubParts ( true, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) ); pcCU->setMergeIndexSubParts( uiMRGIndex, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) ); pcCU->setInterDirSubParts ( uiMRGInterDir, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) ); pcCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMRGMvField[0], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMRGMvField[1], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_0)->setAllMvd ( cMvZero, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField(REF_PIC_LIST_1)->setAllMvd ( cMvZero, ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_0, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPIdxSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( -1, REF_PIC_LIST_1, uiPartAddr, iPartIdx, pcCU->getDepth(uiPartAddr)); } else { // set ME result pcCU->setMergeFlagSubParts( false, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) ); pcCU->setInterDirSubParts ( uiMEInterDir, uiPartAddr, iPartIdx, pcCU->getDepth( uiPartAddr ) ); pcCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMEMvField[0], ePartSize, uiPartAddr, 0, iPartIdx ); pcCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMEMvField[1], ePartSize, uiPartAddr, 0, iPartIdx ); } } #if MCTS_ENC_CHECK if (m_pcEncCfg->getTMCTSSEITileConstraint() && (!checkTMctsMvp(pcCU, iPartIdx))) { pcCU->setTMctsMvpIsValid(false); return; } #endif // MC motionCompensation ( pcCU, pcPredYuv, REF_PIC_LIST_X, iPartIdx ); } // end of for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ ) setWpScalingDistParam( pcCU, -1, REF_PIC_LIST_X ); return; } // AMVP Void TEncSearch::xEstimateMvPredAMVP( TComDataCU* pcCU, TComYuv* pcOrgYuv, UInt uiPartIdx, RefPicList eRefPicList, Int iRefIdx, TComMv& rcMvPred, Bool bFilled, Distortion* puiDistBiP ) { AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); TComMv cBestMv; Int iBestIdx = 0; TComMv cZeroMv; TComMv cMvPred; Distortion uiBestCost = std::numeric_limits::max(); UInt uiPartAddr = 0; Int iRoiWidth, iRoiHeight; Int i; Int minMVPCand; Int maxMVPCand; pcCU->getPartIndexAndSize( uiPartIdx, uiPartAddr, iRoiWidth, iRoiHeight ); // Fill the MV Candidates if (!bFilled) { pcCU->fillMvpCand( uiPartIdx, uiPartAddr, eRefPicList, iRefIdx, pcAMVPInfo ); } // initialize Mvp index & Mvp #if MCTS_ENC_CHECK if (m_pcEncCfg->getTMCTSSEITileConstraint() && pcCU->isLastColumnCTUInTile() && (pcAMVPInfo->numSpatialMVPCandidates < pcAMVPInfo->iN)) { iBestIdx = (pcAMVPInfo->numSpatialMVPCandidates == 0) ? 1 : 0; cBestMv = pcAMVPInfo->m_acMvCand[(pcAMVPInfo->numSpatialMVPCandidates == 0) ? 1 : 0]; minMVPCand = (pcAMVPInfo->numSpatialMVPCandidates == 0) ? 1 : 0; maxMVPCand = (pcAMVPInfo->numSpatialMVPCandidates == 0) ? pcAMVPInfo->iN : 1; } else { iBestIdx = 0; cBestMv = pcAMVPInfo->m_acMvCand[0]; minMVPCand = 0; maxMVPCand = pcAMVPInfo->iN; } #else iBestIdx = 0; cBestMv = pcAMVPInfo->m_acMvCand[0]; minMVPCand = 0; maxMVPCand = pcAMVPInfo->iN; #endif if (pcAMVPInfo->iN <= 1) { rcMvPred = cBestMv; pcCU->setMVPIdxSubParts( iBestIdx, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); if(pcCU->getSlice()->getMvdL1ZeroFlag() && eRefPicList==REF_PIC_LIST_1) { (*puiDistBiP) = xGetTemplateCost( pcCU, uiPartAddr, pcOrgYuv, &m_cYuvPredTemp, rcMvPred, 0, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx, iRoiWidth, iRoiHeight); } return; } if (bFilled) { assert(pcCU->getMVPIdx(eRefPicList,uiPartAddr) >= 0); rcMvPred = pcAMVPInfo->m_acMvCand[pcCU->getMVPIdx(eRefPicList,uiPartAddr)]; return; } m_cYuvPredTemp.clear(); //-- Check Minimum Cost. for ( i = minMVPCand ; i < maxMVPCand; i++) { Distortion uiTmpCost; uiTmpCost = xGetTemplateCost( pcCU, uiPartAddr, pcOrgYuv, &m_cYuvPredTemp, pcAMVPInfo->m_acMvCand[i], i, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx, iRoiWidth, iRoiHeight); if ( uiBestCost > uiTmpCost ) { uiBestCost = uiTmpCost; cBestMv = pcAMVPInfo->m_acMvCand[i]; iBestIdx = i; (*puiDistBiP) = uiTmpCost; } } m_cYuvPredTemp.clear(); // Setting Best MVP rcMvPred = cBestMv; pcCU->setMVPIdxSubParts( iBestIdx, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); return; } UInt TEncSearch::xGetMvpIdxBits(Int iIdx, Int iNum) { assert(iIdx >= 0 && iNum >= 0 && iIdx < iNum); if (iNum == 1) { return 0; } UInt uiLength = 1; Int iTemp = iIdx; if ( iTemp == 0 ) { return uiLength; } Bool bCodeLast = ( iNum-1 > iTemp ); uiLength += (iTemp-1); if( bCodeLast ) { uiLength++; } return uiLength; } Void TEncSearch::xGetBlkBits( PartSize eCUMode, Bool bPSlice, Int iPartIdx, UInt uiLastMode, UInt uiBlkBit[3]) { if ( eCUMode == SIZE_2Nx2N ) { uiBlkBit[0] = (! bPSlice) ? 3 : 1; uiBlkBit[1] = 3; uiBlkBit[2] = 5; } else if ( (eCUMode == SIZE_2NxN || eCUMode == SIZE_2NxnU) || eCUMode == SIZE_2NxnD ) { UInt aauiMbBits[2][3][3] = { { {0,0,3}, {0,0,0}, {0,0,0} } , { {5,7,7}, {7,5,7}, {9-3,9-3,9-3} } }; if ( bPSlice ) { uiBlkBit[0] = 3; uiBlkBit[1] = 0; uiBlkBit[2] = 0; } else { ::memcpy( uiBlkBit, aauiMbBits[iPartIdx][uiLastMode], 3*sizeof(UInt) ); } } else if ( (eCUMode == SIZE_Nx2N || eCUMode == SIZE_nLx2N) || eCUMode == SIZE_nRx2N ) { UInt aauiMbBits[2][3][3] = { { {0,2,3}, {0,0,0}, {0,0,0} } , { {5,7,7}, {7-2,7-2,9-2}, {9-3,9-3,9-3} } }; if ( bPSlice ) { uiBlkBit[0] = 3; uiBlkBit[1] = 0; uiBlkBit[2] = 0; } else { ::memcpy( uiBlkBit, aauiMbBits[iPartIdx][uiLastMode], 3*sizeof(UInt) ); } } else if ( eCUMode == SIZE_NxN ) { uiBlkBit[0] = (! bPSlice) ? 3 : 1; uiBlkBit[1] = 3; uiBlkBit[2] = 5; } else { printf("Wrong!\n"); assert( 0 ); } } Void TEncSearch::xCopyAMVPInfo (AMVPInfo* pSrc, AMVPInfo* pDst) { pDst->iN = pSrc->iN; for (Int i = 0; i < pSrc->iN; i++) { pDst->m_acMvCand[i] = pSrc->m_acMvCand[i]; } } Void TEncSearch::xCheckBestMVP ( TComDataCU* pcCU, RefPicList eRefPicList, TComMv cMv, TComMv& rcMvPred, Int& riMVPIdx, UInt& ruiBits, Distortion& ruiCost ) { AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); assert(pcAMVPInfo->m_acMvCand[riMVPIdx] == rcMvPred); if (pcAMVPInfo->iN < 2) { return; } m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(0) ); m_pcRdCost->setCostScale ( 0 ); Int iBestMVPIdx = riMVPIdx; m_pcRdCost->setPredictor( rcMvPred ); Int iOrgMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer()); iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS]; Int iBestMvBits = iOrgMvBits; #if MCTS_ENC_CHECK Int minMVPCand = 0; Int maxMVPCand = pcAMVPInfo->iN; if (m_pcEncCfg->getTMCTSSEITileConstraint() && pcCU->isLastColumnCTUInTile()) { minMVPCand = (pcAMVPInfo->numSpatialMVPCandidates == 0) ? 1 : 0; maxMVPCand = (pcAMVPInfo->numSpatialMVPCandidates == 0) ? pcAMVPInfo->iN : 1; } for (Int iMVPIdx = minMVPCand; iMVPIdx < maxMVPCand; iMVPIdx++) #else for (Int iMVPIdx = 0; iMVPIdx < pcAMVPInfo->iN; iMVPIdx++) #endif { if (iMVPIdx == riMVPIdx) { continue; } m_pcRdCost->setPredictor( pcAMVPInfo->m_acMvCand[iMVPIdx] ); Int iMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer()); iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS]; if (iMvBits < iBestMvBits) { iBestMvBits = iMvBits; iBestMVPIdx = iMVPIdx; } } if (iBestMVPIdx != riMVPIdx) //if changed { rcMvPred = pcAMVPInfo->m_acMvCand[iBestMVPIdx]; riMVPIdx = iBestMVPIdx; UInt uiOrgBits = ruiBits; ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits; ruiCost = (ruiCost - m_pcRdCost->getCost( uiOrgBits )) + m_pcRdCost->getCost( ruiBits ); } } Distortion TEncSearch::xGetTemplateCost( TComDataCU* pcCU, UInt uiPartAddr, TComYuv* pcOrgYuv, TComYuv* pcTemplateCand, TComMv cMvCand, Int iMVPIdx, Int iMVPNum, RefPicList eRefPicList, Int iRefIdx, Int iSizeX, Int iSizeY ) { Distortion uiCost = std::numeric_limits::max(); TComPicYuv* pcPicYuvRef = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdx )->getPicYuvRec(); pcCU->clipMv( cMvCand ); // prediction pattern if ( pcCU->getSlice()->testWeightPred() && pcCU->getSlice()->getSliceType()==P_SLICE ) { xPredInterBlk( COMPONENT_Y, pcCU, pcPicYuvRef, uiPartAddr, &cMvCand, iSizeX, iSizeY, pcTemplateCand, true, pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) ); } else { xPredInterBlk( COMPONENT_Y, pcCU, pcPicYuvRef, uiPartAddr, &cMvCand, iSizeX, iSizeY, pcTemplateCand, false, pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) ); } if ( pcCU->getSlice()->testWeightPred() && pcCU->getSlice()->getSliceType()==P_SLICE ) { xWeightedPredictionUni( pcCU, pcTemplateCand, uiPartAddr, iSizeX, iSizeY, eRefPicList, pcTemplateCand, iRefIdx ); } // calc distortion uiCost = m_pcRdCost->getDistPart( pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA), pcTemplateCand->getAddr(COMPONENT_Y, uiPartAddr), pcTemplateCand->getStride(COMPONENT_Y), pcOrgYuv->getAddr(COMPONENT_Y, uiPartAddr), pcOrgYuv->getStride(COMPONENT_Y), iSizeX, iSizeY, COMPONENT_Y, DF_SAD ); uiCost = (UInt) m_pcRdCost->calcRdCost( m_auiMVPIdxCost[iMVPIdx][iMVPNum], uiCost, DF_SAD ); return uiCost; } Void TEncSearch::xMotionEstimation( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPartIdx, RefPicList eRefPicList, TComMv* pcMvPred, Int iRefIdxPred, TComMv& rcMv, UInt& ruiBits, Distortion& ruiCost, Bool bBi ) { UInt uiPartAddr; Int iRoiWidth; Int iRoiHeight; TComMv cMvHalf, cMvQter; TComMv cMvSrchRngLT; TComMv cMvSrchRngRB; TComYuv* pcYuv = pcYuvOrg; assert(eRefPicList < MAX_NUM_REF_LIST_ADAPT_SR && iRefIdxPredgetPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight ); if ( bBi ) // Bipredictive ME { TComYuv* pcYuvOther = &m_acYuvPred[1-(Int)eRefPicList]; pcYuv = &m_cYuvPredTemp; pcYuvOrg->copyPartToPartYuv( pcYuv, uiPartAddr, iRoiWidth, iRoiHeight ); pcYuv->removeHighFreq( pcYuvOther, uiPartAddr, iRoiWidth, iRoiHeight, pcCU->getSlice()->getSPS()->getBitDepths().recon, m_pcEncCfg->getClipForBiPredMeEnabled() ); fWeight = 0.5; } m_cDistParam.bIsBiPred = bBi; // Search key pattern initialization #if MCTS_ENC_CHECK Int roiPosX, roiPosY; Int roiW, roiH; pcCU->getPartPosition(iPartIdx, roiPosX, roiPosY, roiW, roiH); assert(roiW == iRoiWidth); assert(roiH == iRoiHeight); cPattern.initPattern( pcYuv->getAddr(COMPONENT_Y, uiPartAddr), iRoiWidth, iRoiHeight, pcYuv->getStride(COMPONENT_Y), pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA), roiPosX, roiPosY); xInitTileBorders(pcCU, &cPattern); #else cPattern.initPattern( pcYuv->getAddr ( COMPONENT_Y, uiPartAddr ), iRoiWidth, iRoiHeight, pcYuv->getStride(COMPONENT_Y), pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) ); #endif Pel* piRefY = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiPartAddr ); Int iRefStride = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getStride(COMPONENT_Y); TComMv cMvPred = *pcMvPred; if ( bBi ) { #if MCTS_ENC_CHECK xSetSearchRange(pcCU, rcMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB, &cPattern); #else xSetSearchRange(pcCU, rcMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB); #endif } else { #if MCTS_ENC_CHECK xSetSearchRange(pcCU, cMvPred, iSrchRng, cMvSrchRngLT, cMvSrchRngRB, &cPattern); #else xSetSearchRange(pcCU, cMvPred, iSrchRng, cMvSrchRngLT, cMvSrchRngRB); #endif } m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) ); m_pcRdCost->setPredictor ( *pcMvPred ); m_pcRdCost->setCostScale ( 2 ); setWpScalingDistParam( pcCU, iRefIdxPred, eRefPicList ); // Do integer search if ( (m_motionEstimationSearchMethod==MESEARCH_FULL) || bBi ) { xPatternSearch ( &cPattern, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost ); } else { rcMv = *pcMvPred; const TComMv *pIntegerMv2Nx2NPred=0; if (pcCU->getPartitionSize(0) != SIZE_2Nx2N || pcCU->getDepth(0) != 0) { pIntegerMv2Nx2NPred = &(m_integerMv2Nx2N[eRefPicList][iRefIdxPred]); } xPatternSearchFast ( pcCU, &cPattern, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost, pIntegerMv2Nx2NPred ); if (pcCU->getPartitionSize(0) == SIZE_2Nx2N) { m_integerMv2Nx2N[eRefPicList][iRefIdxPred] = rcMv; } } m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) ); m_pcRdCost->setCostScale ( 1 ); const Bool bIsLosslessCoded = pcCU->getCUTransquantBypass(uiPartAddr) != 0; xPatternSearchFracDIF( bIsLosslessCoded, &cPattern, piRefY, iRefStride, &rcMv, cMvHalf, cMvQter, ruiCost ); m_pcRdCost->setCostScale( 0 ); rcMv <<= 2; rcMv += (cMvHalf <<= 1); rcMv += cMvQter; UInt uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer() ); ruiBits += uiMvBits; ruiCost = (Distortion)( floor( fWeight * ( (Double)ruiCost - (Double)m_pcRdCost->getCost( uiMvBits ) ) ) + (Double)m_pcRdCost->getCost( ruiBits ) ); } #if MCTS_ENC_CHECK Void TEncSearch::xInitTileBorders(const TComDataCU* const pcCU, TComPattern* pcPatternKey) { if (m_pcEncCfg->getTMCTSSEITileConstraint()) { UInt tileXPosInCtus = 0; UInt tileYPosInCtus = 0; UInt tileWidthtInCtus = 0; UInt tileHeightInCtus = 0; getTilePosition(pcCU, tileXPosInCtus, tileYPosInCtus, tileWidthtInCtus, tileHeightInCtus); const Int ctuLength = pcCU->getPic()->getPicSym()->getSPS().getMaxCUWidth(); // tile position in full pels const Int tileLeftTopPelPosX = ctuLength * tileXPosInCtus; const Int tileLeftTopPelPosY = ctuLength * tileYPosInCtus; const Int tileRightBottomPelPosX = ((tileWidthtInCtus + tileXPosInCtus) * ctuLength) - 1; const Int tileRightBottomPelPosY = ((tileHeightInCtus + tileYPosInCtus) * ctuLength) - 1; pcPatternKey->setTileBorders (tileLeftTopPelPosX,tileLeftTopPelPosY,tileRightBottomPelPosX,tileRightBottomPelPosY); } } #endif Void TEncSearch::xSetSearchRange ( const TComDataCU* const pcCU, const TComMv& cMvPred, const Int iSrchRng, #if MCTS_ENC_CHECK TComMv& rcMvSrchRngLT, TComMv& rcMvSrchRngRB, const TComPattern* const pcPatternKey ) #else TComMv& rcMvSrchRngLT, TComMv& rcMvSrchRngRB ) #endif { Int iMvShift = 2; TComMv cTmpMvPred = cMvPred; pcCU->clipMv( cTmpMvPred ); #if MCTS_ENC_CHECK if (m_pcEncCfg->getTMCTSSEITileConstraint()) { const Int lRangeXLeft = max(cTmpMvPred.getHor() - (iSrchRng << iMvShift), (pcPatternKey->getTileLeftTopPelPosX() - pcPatternKey->getROIYPosX()) << iMvShift); const Int lRangeYTop = max(cTmpMvPred.getVer() - (iSrchRng << iMvShift), (pcPatternKey->getTileLeftTopPelPosY() - pcPatternKey->getROIYPosY()) << iMvShift); const Int lRangeXRight = min(cTmpMvPred.getHor() + (iSrchRng << iMvShift), (pcPatternKey->getTileRightBottomPelPosX() - (pcPatternKey->getROIYPosX() + pcPatternKey->getROIYWidth())) << iMvShift); const Int lRangeYBottom = min(cTmpMvPred.getVer() + (iSrchRng << iMvShift), (pcPatternKey->getTileRightBottomPelPosY() - (pcPatternKey->getROIYPosY() + pcPatternKey->getROIYHeight())) << iMvShift); rcMvSrchRngLT.setHor(lRangeXLeft); rcMvSrchRngLT.setVer(lRangeYTop); rcMvSrchRngRB.setHor(lRangeXRight); rcMvSrchRngRB.setVer(lRangeYBottom); } else { rcMvSrchRngLT.setHor(cTmpMvPred.getHor() - (iSrchRng << iMvShift)); rcMvSrchRngLT.setVer(cTmpMvPred.getVer() - (iSrchRng << iMvShift)); rcMvSrchRngRB.setHor( cTmpMvPred.getHor() + (iSrchRng << iMvShift)); rcMvSrchRngRB.setVer( cTmpMvPred.getVer() + (iSrchRng << iMvShift) ); } #else rcMvSrchRngLT.setHor( cTmpMvPred.getHor() - (iSrchRng << iMvShift) ); rcMvSrchRngLT.setVer( cTmpMvPred.getVer() - (iSrchRng << iMvShift) ); rcMvSrchRngRB.setHor( cTmpMvPred.getHor() + (iSrchRng << iMvShift)); rcMvSrchRngRB.setVer( cTmpMvPred.getVer() + (iSrchRng << iMvShift) ); #endif pcCU->clipMv ( rcMvSrchRngLT ); pcCU->clipMv ( rcMvSrchRngRB ); #if ME_ENABLE_ROUNDING_OF_MVS rcMvSrchRngLT.divideByPowerOf2(iMvShift); rcMvSrchRngRB.divideByPowerOf2(iMvShift); #else rcMvSrchRngLT >>= iMvShift; rcMvSrchRngRB >>= iMvShift; #endif } Void TEncSearch::xPatternSearch( const TComPattern* const pcPatternKey, const Pel* piRefY, const Int iRefStride, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, TComMv& rcMv, Distortion& ruiSAD ) { Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); Distortion uiSad; Distortion uiSadBest = std::numeric_limits::max(); Int iBestX = 0; Int iBestY = 0; //-- jclee for using the SAD function pointer m_pcRdCost->setDistParam( pcPatternKey, piRefY, iRefStride, m_cDistParam ); // fast encoder decision: use subsampled SAD for integer ME if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE3 ) { if ( m_cDistParam.iRows > 8 ) { m_cDistParam.iSubShift = 1; } } piRefY += (iSrchRngVerTop * iRefStride); for ( Int y = iSrchRngVerTop; y <= iSrchRngVerBottom; y++ ) { for ( Int x = iSrchRngHorLeft; x <= iSrchRngHorRight; x++ ) { // find min. distortion position m_cDistParam.pCur = piRefY + x; setDistParamComp(COMPONENT_Y); m_cDistParam.bitDepth = pcPatternKey->getBitDepthY(); uiSad = m_cDistParam.DistFunc( &m_cDistParam ); // motion cost uiSad += m_pcRdCost->getCostOfVectorWithPredictor( x, y ); if ( uiSad < uiSadBest ) { uiSadBest = uiSad; iBestX = x; iBestY = y; m_cDistParam.m_maximumDistortionForEarlyExit = uiSad; } } piRefY += iRefStride; } rcMv.set( iBestX, iBestY ); ruiSAD = uiSadBest - m_pcRdCost->getCostOfVectorWithPredictor( iBestX, iBestY ); return; } Void TEncSearch::xPatternSearchFast( const TComDataCU* const pcCU, const TComPattern* const pcPatternKey, const Pel* const piRefY, const Int iRefStride, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, TComMv& rcMv, Distortion& ruiSAD, const TComMv* const pIntegerMv2Nx2NPred ) { assert (MD_LEFT < NUM_MV_PREDICTORS); pcCU->getMvPredLeft ( m_acMvPredictors[MD_LEFT] ); assert (MD_ABOVE < NUM_MV_PREDICTORS); pcCU->getMvPredAbove ( m_acMvPredictors[MD_ABOVE] ); assert (MD_ABOVE_RIGHT < NUM_MV_PREDICTORS); pcCU->getMvPredAboveRight ( m_acMvPredictors[MD_ABOVE_RIGHT] ); switch ( m_motionEstimationSearchMethod ) { case MESEARCH_DIAMOND: xTZSearch( pcCU, pcPatternKey, piRefY, iRefStride, pcMvSrchRngLT, pcMvSrchRngRB, rcMv, ruiSAD, pIntegerMv2Nx2NPred, false ); break; case MESEARCH_SELECTIVE: xTZSearchSelective( pcCU, pcPatternKey, piRefY, iRefStride, pcMvSrchRngLT, pcMvSrchRngRB, rcMv, ruiSAD, pIntegerMv2Nx2NPred ); break; case MESEARCH_DIAMOND_ENHANCED: xTZSearch( pcCU, pcPatternKey, piRefY, iRefStride, pcMvSrchRngLT, pcMvSrchRngRB, rcMv, ruiSAD, pIntegerMv2Nx2NPred, true ); break; case MESEARCH_FULL: // shouldn't get here. default: break; } } Void TEncSearch::xTZSearch( const TComDataCU* const pcCU, const TComPattern* const pcPatternKey, const Pel* const piRefY, const Int iRefStride, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, TComMv& rcMv, Distortion& ruiSAD, const TComMv* const pIntegerMv2Nx2NPred, const Bool bExtendedSettings) { const Bool bUseAdaptiveRaster = bExtendedSettings; const Int iRaster = 5; const Bool bTestOtherPredictedMV = bExtendedSettings; const Bool bTestZeroVector = true; const Bool bTestZeroVectorStart = bExtendedSettings; const Bool bTestZeroVectorStop = false; const Bool bFirstSearchDiamond = true; // 1 = xTZ8PointDiamondSearch 0 = xTZ8PointSquareSearch const Bool bFirstCornersForDiamondDist1 = bExtendedSettings; const Bool bFirstSearchStop = m_pcEncCfg->getFastMEAssumingSmootherMVEnabled(); const UInt uiFirstSearchRounds = 3; // first search stop X rounds after best match (must be >=1) const Bool bEnableRasterSearch = true; const Bool bAlwaysRasterSearch = bExtendedSettings; // true: BETTER but factor 2 slower const Bool bRasterRefinementEnable = false; // enable either raster refinement or star refinement const Bool bRasterRefinementDiamond = false; // 1 = xTZ8PointDiamondSearch 0 = xTZ8PointSquareSearch const Bool bRasterRefinementCornersForDiamondDist1 = bExtendedSettings; const Bool bStarRefinementEnable = true; // enable either star refinement or raster refinement const Bool bStarRefinementDiamond = true; // 1 = xTZ8PointDiamondSearch 0 = xTZ8PointSquareSearch const Bool bStarRefinementCornersForDiamondDist1 = bExtendedSettings; const Bool bStarRefinementStop = false; const UInt uiStarRefinementRounds = 2; // star refinement stop X rounds after best match (must be >=1) const Bool bNewZeroNeighbourhoodTest = bExtendedSettings; UInt uiSearchRange = m_iSearchRange; pcCU->clipMv( rcMv ); #if ME_ENABLE_ROUNDING_OF_MVS rcMv.divideByPowerOf2(2); #else rcMv >>= 2; #endif // init TZSearchStruct IntTZSearchStruct cStruct; cStruct.iBestX = 0; cStruct.iBestY = 0; cStruct.iYStride = iRefStride; cStruct.piRefY = piRefY; cStruct.uiBestSad = MAX_UINT; // set rcMv (Median predictor) as start point and as best point xTZSearchHelp( pcPatternKey, cStruct, rcMv.getHor(), rcMv.getVer(), 0, 0 ); // test whether one of PRED_A, PRED_B, PRED_C MV is better start point than Median predictor if ( bTestOtherPredictedMV ) { for ( UInt index = 0; index < NUM_MV_PREDICTORS; index++ ) { TComMv cMv = m_acMvPredictors[index]; pcCU->clipMv( cMv ); #if ME_ENABLE_ROUNDING_OF_MVS cMv.divideByPowerOf2(2); #else cMv >>= 2; #endif if (cMv != rcMv && (cMv.getHor() != cStruct.iBestX && cMv.getVer() != cStruct.iBestY)) { // only test cMV if not obviously previously tested. xTZSearchHelp( pcPatternKey, cStruct, cMv.getHor(), cMv.getVer(), 0, 0 ); } } } // test whether zero Mv is better start point than Median predictor if ( bTestZeroVector ) { if ((rcMv.getHor() != 0 || rcMv.getVer() != 0) && (0 != cStruct.iBestX || 0 != cStruct.iBestY)) { // only test 0-vector if not obviously previously tested. xTZSearchHelp( pcPatternKey, cStruct, 0, 0, 0, 0 ); } } Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); if (pIntegerMv2Nx2NPred != 0) { TComMv integerMv2Nx2NPred = *pIntegerMv2Nx2NPred; integerMv2Nx2NPred <<= 2; pcCU->clipMv( integerMv2Nx2NPred ); #if ME_ENABLE_ROUNDING_OF_MVS integerMv2Nx2NPred.divideByPowerOf2(2); #else integerMv2Nx2NPred >>= 2; #endif if ((rcMv != integerMv2Nx2NPred) && (integerMv2Nx2NPred.getHor() != cStruct.iBestX || integerMv2Nx2NPred.getVer() != cStruct.iBestY)) { // only test integerMv2Nx2NPred if not obviously previously tested. xTZSearchHelp(pcPatternKey, cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0); } // reset search range TComMv cMvSrchRngLT; TComMv cMvSrchRngRB; Int iSrchRng = m_iSearchRange; TComMv currBestMv(cStruct.iBestX, cStruct.iBestY ); currBestMv <<= 2; #if MCTS_ENC_CHECK xSetSearchRange(pcCU, currBestMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB, pcPatternKey); #else xSetSearchRange(pcCU, currBestMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB); #endif iSrchRngHorLeft = cMvSrchRngLT.getHor(); iSrchRngHorRight = cMvSrchRngRB.getHor(); iSrchRngVerTop = cMvSrchRngLT.getVer(); iSrchRngVerBottom = cMvSrchRngRB.getVer(); } // start search Int iDist = 0; Int iStartX = cStruct.iBestX; Int iStartY = cStruct.iBestY; const Bool bBestCandidateZero = (cStruct.iBestX == 0) && (cStruct.iBestY == 0); // first search around best position up to now. // The following works as a "subsampled/log" window search around the best candidate for ( iDist = 1; iDist <= (Int)uiSearchRange; iDist*=2 ) { if ( bFirstSearchDiamond == 1 ) { xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist, bFirstCornersForDiamondDist1 ); } else { xTZ8PointSquareSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist ); } if ( bFirstSearchStop && ( cStruct.uiBestRound >= uiFirstSearchRounds ) ) // stop criterion { break; } } if (!bNewZeroNeighbourhoodTest) { // test whether zero Mv is a better start point than Median predictor if ( bTestZeroVectorStart && ((cStruct.iBestX != 0) || (cStruct.iBestY != 0)) ) { xTZSearchHelp( pcPatternKey, cStruct, 0, 0, 0, 0 ); if ( (cStruct.iBestX == 0) && (cStruct.iBestY == 0) ) { // test its neighborhood for ( iDist = 1; iDist <= (Int)uiSearchRange; iDist*=2 ) { xTZ8PointDiamondSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, 0, 0, iDist, false ); if ( bTestZeroVectorStop && (cStruct.uiBestRound > 0) ) // stop criterion { break; } } } } } else { // Test also zero neighbourhood but with half the range // It was reported that the original (above) search scheme using bTestZeroVectorStart did not // make sense since one would have already checked the zero candidate earlier // and thus the conditions for that test would have not been satisfied if (bTestZeroVectorStart == true && bBestCandidateZero != true) { for ( iDist = 1; iDist <= ((Int)uiSearchRange >> 1); iDist*=2 ) { xTZ8PointDiamondSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, 0, 0, iDist, false ); if ( bTestZeroVectorStop && (cStruct.uiBestRound > 2) ) // stop criterion { break; } } } } // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1 if ( cStruct.uiBestDistance == 1 ) { cStruct.uiBestDistance = 0; xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB ); } // raster search if distance is too big if (bUseAdaptiveRaster) { Int iWindowSize = iRaster; Int iSrchRngRasterLeft = iSrchRngHorLeft; Int iSrchRngRasterRight = iSrchRngHorRight; Int iSrchRngRasterTop = iSrchRngVerTop; Int iSrchRngRasterBottom = iSrchRngVerBottom; if (!(bEnableRasterSearch && ( ((Int)(cStruct.uiBestDistance) > iRaster)))) { iWindowSize ++; iSrchRngRasterLeft /= 2; iSrchRngRasterRight /= 2; iSrchRngRasterTop /= 2; iSrchRngRasterBottom /= 2; } cStruct.uiBestDistance = iWindowSize; for ( iStartY = iSrchRngRasterTop; iStartY <= iSrchRngRasterBottom; iStartY += iWindowSize ) { for ( iStartX = iSrchRngRasterLeft; iStartX <= iSrchRngRasterRight; iStartX += iWindowSize ) { xTZSearchHelp( pcPatternKey, cStruct, iStartX, iStartY, 0, iWindowSize ); } } } else { if ( bEnableRasterSearch && ( ((Int)(cStruct.uiBestDistance) > iRaster) || bAlwaysRasterSearch ) ) { cStruct.uiBestDistance = iRaster; for ( iStartY = iSrchRngVerTop; iStartY <= iSrchRngVerBottom; iStartY += iRaster ) { for ( iStartX = iSrchRngHorLeft; iStartX <= iSrchRngHorRight; iStartX += iRaster ) { xTZSearchHelp( pcPatternKey, cStruct, iStartX, iStartY, 0, iRaster ); } } } } // raster refinement if ( bRasterRefinementEnable && cStruct.uiBestDistance > 0 ) { while ( cStruct.uiBestDistance > 0 ) { iStartX = cStruct.iBestX; iStartY = cStruct.iBestY; if ( cStruct.uiBestDistance > 1 ) { iDist = cStruct.uiBestDistance >>= 1; if ( bRasterRefinementDiamond == 1 ) { xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist, bRasterRefinementCornersForDiamondDist1 ); } else { xTZ8PointSquareSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist ); } } // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1 if ( cStruct.uiBestDistance == 1 ) { cStruct.uiBestDistance = 0; if ( cStruct.ucPointNr != 0 ) { xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB ); } } } } // star refinement if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 ) { while ( cStruct.uiBestDistance > 0 ) { iStartX = cStruct.iBestX; iStartY = cStruct.iBestY; cStruct.uiBestDistance = 0; cStruct.ucPointNr = 0; for ( iDist = 1; iDist < (Int)uiSearchRange + 1; iDist*=2 ) { if ( bStarRefinementDiamond == 1 ) { xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist, bStarRefinementCornersForDiamondDist1 ); } else { xTZ8PointSquareSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist ); } if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion { break; } } // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1 if ( cStruct.uiBestDistance == 1 ) { cStruct.uiBestDistance = 0; if ( cStruct.ucPointNr != 0 ) { xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB ); } } } } // write out best match rcMv.set( cStruct.iBestX, cStruct.iBestY ); ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY ); } Void TEncSearch::xTZSearchSelective( const TComDataCU* const pcCU, const TComPattern* const pcPatternKey, const Pel* const piRefY, const Int iRefStride, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, TComMv &rcMv, Distortion &ruiSAD, const TComMv* const pIntegerMv2Nx2NPred ) { const Bool bTestOtherPredictedMV = true; const Bool bTestZeroVector = true; const Bool bEnableRasterSearch = true; const Bool bAlwaysRasterSearch = false; // 1: BETTER but factor 15x slower const Bool bStarRefinementEnable = true; // enable either star refinement or raster refinement const Bool bStarRefinementDiamond = true; // 1 = xTZ8PointDiamondSearch 0 = xTZ8PointSquareSearch const Bool bStarRefinementStop = false; const UInt uiStarRefinementRounds = 2; // star refinement stop X rounds after best match (must be >=1) const UInt uiSearchRange = m_iSearchRange; const Int uiSearchRangeInitial = m_iSearchRange >> 2; const Int uiSearchStep = 4; const Int iMVDistThresh = 8; Int iSrchRngHorLeft = pcMvSrchRngLT->getHor(); Int iSrchRngHorRight = pcMvSrchRngRB->getHor(); Int iSrchRngVerTop = pcMvSrchRngLT->getVer(); Int iSrchRngVerBottom = pcMvSrchRngRB->getVer(); Int iFirstSrchRngHorLeft = 0; Int iFirstSrchRngHorRight = 0; Int iFirstSrchRngVerTop = 0; Int iFirstSrchRngVerBottom = 0; Int iStartX = 0; Int iStartY = 0; Int iBestX = 0; Int iBestY = 0; Int iDist = 0; pcCU->clipMv( rcMv ); #if ME_ENABLE_ROUNDING_OF_MVS rcMv.divideByPowerOf2(2); #else rcMv >>= 2; #endif // init TZSearchStruct IntTZSearchStruct cStruct; cStruct.iYStride = iRefStride; cStruct.piRefY = piRefY; cStruct.uiBestSad = MAX_UINT; cStruct.iBestX = 0; cStruct.iBestY = 0; // set rcMv (Median predictor) as start point and as best point xTZSearchHelp( pcPatternKey, cStruct, rcMv.getHor(), rcMv.getVer(), 0, 0 ); // test whether one of PRED_A, PRED_B, PRED_C MV is better start point than Median predictor if ( bTestOtherPredictedMV ) { for ( UInt index = 0; index < NUM_MV_PREDICTORS; index++ ) { TComMv cMv = m_acMvPredictors[index]; pcCU->clipMv( cMv ); #if ME_ENABLE_ROUNDING_OF_MVS cMv.divideByPowerOf2(2); #else cMv >>= 2; #endif xTZSearchHelp( pcPatternKey, cStruct, cMv.getHor(), cMv.getVer(), 0, 0 ); } } // test whether zero Mv is better start point than Median predictor if ( bTestZeroVector ) { xTZSearchHelp( pcPatternKey, cStruct, 0, 0, 0, 0 ); } if ( pIntegerMv2Nx2NPred != 0 ) { TComMv integerMv2Nx2NPred = *pIntegerMv2Nx2NPred; integerMv2Nx2NPred <<= 2; pcCU->clipMv( integerMv2Nx2NPred ); #if ME_ENABLE_ROUNDING_OF_MVS integerMv2Nx2NPred.divideByPowerOf2(2); #else integerMv2Nx2NPred >>= 2; #endif xTZSearchHelp(pcPatternKey, cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0); // reset search range TComMv cMvSrchRngLT; TComMv cMvSrchRngRB; Int iSrchRng = m_iSearchRange; TComMv currBestMv(cStruct.iBestX, cStruct.iBestY ); currBestMv <<= 2; #if MCTS_ENC_CHECK xSetSearchRange(pcCU, currBestMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB, pcPatternKey); #else xSetSearchRange(pcCU, currBestMv, iSrchRng, cMvSrchRngLT, cMvSrchRngRB); #endif iSrchRngHorLeft = cMvSrchRngLT.getHor(); iSrchRngHorRight = cMvSrchRngRB.getHor(); iSrchRngVerTop = cMvSrchRngLT.getVer(); iSrchRngVerBottom = cMvSrchRngRB.getVer(); } // Initial search iBestX = cStruct.iBestX; iBestY = cStruct.iBestY; iFirstSrchRngHorLeft = ((iBestX - uiSearchRangeInitial) > iSrchRngHorLeft) ? (iBestX - uiSearchRangeInitial) : iSrchRngHorLeft; iFirstSrchRngVerTop = ((iBestY - uiSearchRangeInitial) > iSrchRngVerTop) ? (iBestY - uiSearchRangeInitial) : iSrchRngVerTop; iFirstSrchRngHorRight = ((iBestX + uiSearchRangeInitial) < iSrchRngHorRight) ? (iBestX + uiSearchRangeInitial) : iSrchRngHorRight; iFirstSrchRngVerBottom = ((iBestY + uiSearchRangeInitial) < iSrchRngVerBottom) ? (iBestY + uiSearchRangeInitial) : iSrchRngVerBottom; for ( iStartY = iFirstSrchRngVerTop; iStartY <= iFirstSrchRngVerBottom; iStartY += uiSearchStep ) { for ( iStartX = iFirstSrchRngHorLeft; iStartX <= iFirstSrchRngHorRight; iStartX += uiSearchStep ) { xTZSearchHelp( pcPatternKey, cStruct, iStartX, iStartY, 0, 0 ); xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, 1, false ); xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, 2, false ); } } Int iMaxMVDistToPred = (abs(cStruct.iBestX - iBestX) > iMVDistThresh || abs(cStruct.iBestY - iBestY) > iMVDistThresh); //full search with early exit if MV is distant from predictors if ( bEnableRasterSearch && (iMaxMVDistToPred || bAlwaysRasterSearch) ) { for ( iStartY = iSrchRngVerTop; iStartY <= iSrchRngVerBottom; iStartY += 1 ) { for ( iStartX = iSrchRngHorLeft; iStartX <= iSrchRngHorRight; iStartX += 1 ) { xTZSearchHelp( pcPatternKey, cStruct, iStartX, iStartY, 0, 1 ); } } } //Smaller MV, refine around predictor else if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 ) { // start refinement while ( cStruct.uiBestDistance > 0 ) { iStartX = cStruct.iBestX; iStartY = cStruct.iBestY; cStruct.uiBestDistance = 0; cStruct.ucPointNr = 0; for ( iDist = 1; iDist < (Int)uiSearchRange + 1; iDist*=2 ) { if ( bStarRefinementDiamond == 1 ) { xTZ8PointDiamondSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist, false ); } else { xTZ8PointSquareSearch ( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB, iStartX, iStartY, iDist ); } if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion { break; } } // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1 if ( cStruct.uiBestDistance == 1 ) { cStruct.uiBestDistance = 0; if ( cStruct.ucPointNr != 0 ) { xTZ2PointSearch( pcPatternKey, cStruct, pcMvSrchRngLT, pcMvSrchRngRB ); } } } } // write out best match rcMv.set( cStruct.iBestX, cStruct.iBestY ); ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY ); } Void TEncSearch::xPatternSearchFracDIF( Bool bIsLosslessCoded, TComPattern* pcPatternKey, Pel* piRefY, Int iRefStride, TComMv* pcMvInt, TComMv& rcMvHalf, TComMv& rcMvQter, Distortion& ruiCost ) { // Reference pattern initialization (integer scale) TComPattern cPatternRoi; Int iOffset = pcMvInt->getHor() + pcMvInt->getVer() * iRefStride; cPatternRoi.initPattern(piRefY + iOffset, pcPatternKey->getROIYWidth(), pcPatternKey->getROIYHeight(), iRefStride, #if MCTS_ENC_CHECK pcPatternKey->getBitDepthY(), pcPatternKey->getROIYPosX(), pcPatternKey->getROIYPosY()); #else pcPatternKey->getBitDepthY()); #endif #if MCTS_ENC_CHECK cPatternRoi.setTileBorders(pcPatternKey->getTileLeftTopPelPosX(), pcPatternKey->getTileLeftTopPelPosY(), pcPatternKey->getTileRightBottomPelPosX(), pcPatternKey->getTileRightBottomPelPosY()); #endif // Half-pel refinement xExtDIFUpSamplingH ( &cPatternRoi ); rcMvHalf = *pcMvInt; rcMvHalf <<= 1; // for mv-cost TComMv baseRefMv(0, 0); ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 2, rcMvHalf, !bIsLosslessCoded ); m_pcRdCost->setCostScale( 0 ); xExtDIFUpSamplingQ ( &cPatternRoi, rcMvHalf ); baseRefMv = rcMvHalf; baseRefMv <<= 1; rcMvQter = *pcMvInt; rcMvQter <<= 1; // for mv-cost rcMvQter += rcMvHalf; rcMvQter <<= 1; ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded ); } //! encode residual and calculate rate-distortion for a CU block Void TEncSearch::encodeResAndCalcRdInterCU( TComDataCU* pcCU, TComYuv* pcYuvOrg, TComYuv* pcYuvPred, TComYuv* pcYuvResi, TComYuv* pcYuvResiBest, TComYuv* pcYuvRec, Bool bSkipResidual DEBUG_STRING_FN_DECLARE(sDebug) ) { assert ( !pcCU->isIntra(0) ); const UInt cuWidthPixels = pcCU->getWidth ( 0 ); const UInt cuHeightPixels = pcCU->getHeight( 0 ); const Int numValidComponents = pcCU->getPic()->getNumberValidComponents(); const TComSPS &sps=*(pcCU->getSlice()->getSPS()); // The pcCU is not marked as skip-mode at this point, and its m_pcTrCoeff, m_pcArlCoeff, m_puhCbf, m_puhTrIdx will all be 0. // due to prior calls to TComDataCU::initEstData( ); if ( bSkipResidual ) // No residual coding : SKIP mode { pcCU->setSkipFlagSubParts( true, 0, pcCU->getDepth(0) ); pcYuvResi->clear(); pcYuvPred->copyToPartYuv( pcYuvRec, 0 ); Distortion distortion = 0; for (Int comp=0; comp < numValidComponents; comp++) { const ComponentID compID=ComponentID(comp); const UInt csx=pcYuvOrg->getComponentScaleX(compID); const UInt csy=pcYuvOrg->getComponentScaleY(compID); distortion += m_pcRdCost->getDistPart( sps.getBitDepth(toChannelType(compID)), pcYuvRec->getAddr(compID), pcYuvRec->getStride(compID), pcYuvOrg->getAddr(compID), pcYuvOrg->getStride(compID), cuWidthPixels >> csx, cuHeightPixels >> csy, compID); } m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_CURR_BEST]); m_pcEntropyCoder->resetBits(); if (pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag(pcCU, 0, true); } m_pcEntropyCoder->encodeSkipFlag(pcCU, 0, true); m_pcEntropyCoder->encodeMergeIndex( pcCU, 0, true ); UInt uiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); pcCU->getTotalBits() = uiBits; pcCU->getTotalDistortion() = distortion; pcCU->getTotalCost() = m_pcRdCost->calcRdCost( uiBits, distortion ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_TEMP_BEST]); #if DEBUG_STRING pcYuvResiBest->clear(); // Clear the residual image, if we didn't code it. for(UInt i=0; isubtract( pcYuvOrg, pcYuvPred, 0, cuWidthPixels ); TComTURecurse tuLevel0(pcCU, 0); Double nonZeroCost = 0; UInt nonZeroBits = 0; Distortion nonZeroDistortion = 0; Distortion zeroDistortion = 0; m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ pcCU->getDepth( 0 ) ][ CI_CURR_BEST ] ); xEstimateInterResidualQT( pcYuvResi, nonZeroCost, nonZeroBits, nonZeroDistortion, &zeroDistortion, tuLevel0 DEBUG_STRING_PASS_INTO(sDebug) ); // ------------------------------------------------------- // set the coefficients in the pcCU, and also calculates the residual data. // If a block full of 0's is efficient, then just use 0's. // The costs at this point do not include header bits. m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQtRootCbfZero( ); const UInt zeroResiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); const Double zeroCost = (pcCU->isLosslessCoded( 0 )) ? (nonZeroCost+1) : (m_pcRdCost->calcRdCost( zeroResiBits, zeroDistortion )); if ( zeroCost < nonZeroCost || !pcCU->getQtRootCbf(0) ) { const UInt uiQPartNum = tuLevel0.GetAbsPartIdxNumParts(); ::memset( pcCU->getTransformIdx() , 0, uiQPartNum * sizeof(UChar) ); for (Int comp=0; comp < numValidComponents; comp++) { const ComponentID component = ComponentID(comp); ::memset( pcCU->getCbf( component ) , 0, uiQPartNum * sizeof(UChar) ); ::memset( pcCU->getCrossComponentPredictionAlpha(component), 0, ( uiQPartNum * sizeof(SChar) ) ); } static const UInt useTS[MAX_NUM_COMPONENT]={0,0,0}; pcCU->setTransformSkipSubParts ( useTS, 0, pcCU->getDepth(0) ); #if DEBUG_STRING sDebug.clear(); for(UInt i=0; iload( m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_CURR_BEST] ); UInt finalBits = 0; xAddSymbolBitsInter( pcCU, finalBits ); // we've now encoded the pcCU, and so have a valid bit cost if ( !pcCU->getQtRootCbf( 0 ) ) { pcYuvResiBest->clear(); // Clear the residual image, if we didn't code it. } else { xSetInterResidualQTData( pcYuvResiBest, true, tuLevel0 ); // else set the residual image data pcYUVResiBest from the various temp images. } m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ pcCU->getDepth( 0 ) ][ CI_TEMP_BEST ] ); pcYuvRec->addClip ( pcYuvPred, pcYuvResiBest, 0, cuWidthPixels, sps.getBitDepths() ); // update with clipped distortion and cost (previously unclipped reconstruction values were used) Distortion finalDistortion = 0; for(Int comp=0; compgetDistPart( sps.getBitDepth(toChannelType(compID)), pcYuvRec->getAddr(compID ), pcYuvRec->getStride(compID ), pcYuvOrg->getAddr(compID ), pcYuvOrg->getStride(compID), cuWidthPixels >> pcYuvOrg->getComponentScaleX(compID), cuHeightPixels >> pcYuvOrg->getComponentScaleY(compID), compID); } pcCU->getTotalBits() = finalBits; pcCU->getTotalDistortion() = finalDistortion; pcCU->getTotalCost() = m_pcRdCost->calcRdCost( finalBits, finalDistortion ); } Void TEncSearch::xEstimateInterResidualQT( TComYuv *pcResi, Double &rdCost, UInt &ruiBits, Distortion &ruiDist, Distortion *puiZeroDist, TComTU &rTu DEBUG_STRING_FN_DECLARE(sDebug) ) { TComDataCU *pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const UInt uiDepth = rTu.GetTransformDepthTotal(); const UInt uiTrMode = rTu.GetTransformDepthRel(); const UInt subTUDepth = uiTrMode + 1; const UInt numValidComp = pcCU->getPic()->getNumberValidComponents(); DEBUG_STRING_NEW(sSingleStringComp[MAX_NUM_COMPONENT]) assert( pcCU->getDepth( 0 ) == pcCU->getDepth( uiAbsPartIdx ) ); const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); UInt SplitFlag = ((pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) && pcCU->isInter(uiAbsPartIdx) && ( pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N )); #if DEBUG_STRING const Int debugPredModeMask = DebugStringGetPredModeMask(pcCU->getPredictionMode(uiAbsPartIdx)); #endif Bool bCheckFull; if ( SplitFlag && uiDepth == pcCU->getDepth(uiAbsPartIdx) && ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) ) { bCheckFull = false; } else { bCheckFull = ( uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ); } const Bool bCheckSplit = ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); assert( bCheckFull || bCheckSplit ); // code full block Double dSingleCost = MAX_DOUBLE; UInt uiSingleBits = 0; Distortion uiSingleDistComp [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {{0,0},{0,0},{0,0}}; Distortion uiSingleDist = 0; TCoeff uiAbsSum [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {{0,0},{0,0},{0,0}}; UInt uiBestTransformMode [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {{0,0},{0,0},{0,0}}; // Stores the best explicit RDPCM mode for a TU encoded without split UInt bestExplicitRdpcmModeUnSplit[MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {{3,3}, {3,3}, {3,3}}; SChar bestCrossCPredictionAlpha [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {{0,0},{0,0},{0,0}}; m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); if( bCheckFull ) { Double minCost[MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/]; Bool checkTransformSkip[MAX_NUM_COMPONENT]; pcCU->setTrIdxSubParts( uiTrMode, uiAbsPartIdx, uiDepth ); m_pcEntropyCoder->resetBits(); memset( m_pTempPel, 0, sizeof( Pel ) * rTu.getRect(COMPONENT_Y).width * rTu.getRect(COMPONENT_Y).height ); // not necessary needed for inside of recursion (only at the beginning) const UInt uiQTTempAccessLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; TCoeff *pcCoeffCurr[MAX_NUM_COMPONENT]; #if ADAPTIVE_QP_SELECTION TCoeff *pcArlCoeffCurr[MAX_NUM_COMPONENT]; #endif for(UInt i=0; igetSlice()->getSPS()->getBitDepth(toChannelType(compID)); pcCoeffCurr[compID] = m_ppcQTTempCoeff[compID][uiQTTempAccessLayer] + rTu.getCoefficientOffset(compID); #if ADAPTIVE_QP_SELECTION pcArlCoeffCurr[compID] = m_ppcQTTempArlCoeff[compID ][uiQTTempAccessLayer] + rTu.getCoefficientOffset(compID); #endif if(rTu.ProcessComponentSection(compID)) { const QpParam cQP(*pcCU, compID); checkTransformSkip[compID] = pcCU->getSlice()->getPPS()->getUseTransformSkip() && TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(compID), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()) && (!pcCU->isLosslessCoded(0)); const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height; TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID); const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID); do { const UInt subTUIndex = TUIterator.GetSectionNumber(); const UInt subTUAbsPartIdx = TUIterator.GetAbsPartIdxTU(compID); const TComRectangle &tuCompRect = TUIterator.getRect(compID); const UInt subTUBufferOffset = tuCompRect.width * tuCompRect.height * subTUIndex; TCoeff *currentCoefficients = pcCoeffCurr[compID] + subTUBufferOffset; #if ADAPTIVE_QP_SELECTION TCoeff *currentARLCoefficients = pcArlCoeffCurr[compID] + subTUBufferOffset; #endif const Bool isCrossCPredictionAvailable = isChroma(compID) && pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && (pcCU->getCbf(subTUAbsPartIdx, COMPONENT_Y, uiTrMode) != 0); SChar preCalcAlpha = 0; const Pel *pLumaResi = m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix( COMPONENT_Y, rTu.getRect( COMPONENT_Y ).x0, rTu.getRect( COMPONENT_Y ).y0 ); if (isCrossCPredictionAvailable) { const Bool bUseReconstructedResidualForEstimate = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate(); const Pel *const lumaResidualForEstimate = bUseReconstructedResidualForEstimate ? pLumaResi : pcResi->getAddrPix(COMPONENT_Y, tuCompRect.x0, tuCompRect.y0); const UInt lumaResidualStrideForEstimate = bUseReconstructedResidualForEstimate ? m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(COMPONENT_Y) : pcResi->getStride(COMPONENT_Y); preCalcAlpha = xCalcCrossComponentPredictionAlpha(TUIterator, compID, lumaResidualForEstimate, pcResi->getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), tuCompRect.width, tuCompRect.height, lumaResidualStrideForEstimate, pcResi->getStride(compID)); } const Int transformSkipModesToTest = checkTransformSkip[compID] ? 2 : 1; const Int crossCPredictionModesToTest = (preCalcAlpha != 0) ? 2 : 1; // preCalcAlpha cannot be anything other than 0 if isCrossCPredictionAvailable is false const Bool isOneMode = (crossCPredictionModesToTest == 1) && (transformSkipModesToTest == 1); for (Int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++) { pcCU->setTransformSkipPartRange(transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU); for (Int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++) { const Bool isFirstMode = (transformSkipModeId == 0) && (crossCPredictionModeId == 0); const Bool bUseCrossCPrediction = crossCPredictionModeId != 0; m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); pcCU->setTransformSkipPartRange(transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU); pcCU->setCrossComponentPredictionAlphaPartRange((bUseCrossCPrediction ? preCalcAlpha : 0), compID, subTUAbsPartIdx, partIdxesPerSubTU ); if ((compID != COMPONENT_Cr) && ((transformSkipModeId == 1) ? m_pcEncCfg->getUseRDOQTS() : m_pcEncCfg->getUseRDOQ())) { COEFF_SCAN_TYPE scanType = COEFF_SCAN_TYPE(pcCU->getCoefScanIdx(uiAbsPartIdx, tuCompRect.width, tuCompRect.height, compID)); m_pcEntropyCoder->estimateBit(m_pcTrQuant->m_pcEstBitsSbac, tuCompRect.width, tuCompRect.height, toChannelType(compID), scanType); } #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(compID); #endif Pel *pcResiCurrComp = m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0); UInt resiStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID); TCoeff bestCoeffComp [MAX_TU_SIZE*MAX_TU_SIZE]; Pel bestResiComp [MAX_TU_SIZE*MAX_TU_SIZE]; #if ADAPTIVE_QP_SELECTION TCoeff bestArlCoeffComp[MAX_TU_SIZE*MAX_TU_SIZE]; #endif TCoeff currAbsSum = 0; UInt currCompBits = 0; Distortion currCompDist = 0; Double currCompCost = 0; UInt nonCoeffBits = 0; Distortion nonCoeffDist = 0; Double nonCoeffCost = 0; if(!isOneMode && !isFirstMode) { memcpy(bestCoeffComp, currentCoefficients, (sizeof(TCoeff) * tuCompRect.width * tuCompRect.height)); #if ADAPTIVE_QP_SELECTION memcpy(bestArlCoeffComp, currentARLCoefficients, (sizeof(TCoeff) * tuCompRect.width * tuCompRect.height)); #endif for(Int y = 0; y < tuCompRect.height; y++) { memcpy(&bestResiComp[y * tuCompRect.width], (pcResiCurrComp + (y * resiStride)), (sizeof(Pel) * tuCompRect.width)); } } if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction(TUIterator, compID, pLumaResi, pcResi->getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), crossCPredictedResidualBuffer, tuCompRect.width, tuCompRect.height, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(COMPONENT_Y), pcResi->getStride(compID), tuCompRect.width, false); m_pcTrQuant->transformNxN(TUIterator, compID, crossCPredictedResidualBuffer, tuCompRect.width, currentCoefficients, #if ADAPTIVE_QP_SELECTION currentARLCoefficients, #endif currAbsSum, cQP); } else { m_pcTrQuant->transformNxN(TUIterator, compID, pcResi->getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), pcResi->getStride(compID), currentCoefficients, #if ADAPTIVE_QP_SELECTION currentARLCoefficients, #endif currAbsSum, cQP); } if(isFirstMode || (currAbsSum == 0)) { if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction(TUIterator, compID, pLumaResi, m_pTempPel, m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), tuCompRect.width, tuCompRect.height, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(COMPONENT_Y), tuCompRect.width, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID), true); nonCoeffDist = m_pcRdCost->getDistPart( channelBitDepth, m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride( compID ), pcResi->getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), pcResi->getStride(compID), tuCompRect.width, tuCompRect.height, compID); // initialized with zero residual distortion } else { nonCoeffDist = m_pcRdCost->getDistPart( channelBitDepth, m_pTempPel, tuCompRect.width, pcResi->getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), pcResi->getStride(compID), tuCompRect.width, tuCompRect.height, compID); // initialized with zero residual distortion } m_pcEntropyCoder->encodeQtCbfZero( TUIterator, toChannelType(compID) ); if ( isCrossCPredictionAvailable ) { m_pcEntropyCoder->encodeCrossComponentPrediction( TUIterator, compID ); } nonCoeffBits = m_pcEntropyCoder->getNumberOfWrittenBits(); nonCoeffCost = m_pcRdCost->calcRdCost( nonCoeffBits, nonCoeffDist ); } if((puiZeroDist != NULL) && isFirstMode) { *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion } DEBUG_STRING_NEW(sSingleStringTest) if( currAbsSum > 0 ) //if non-zero coefficients are present, a residual needs to be derived for further prediction { if (isFirstMode) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); } m_pcEntropyCoder->encodeQtCbf( TUIterator, compID, true ); if (isCrossCPredictionAvailable) { m_pcEntropyCoder->encodeCrossComponentPrediction( TUIterator, compID ); } m_pcEntropyCoder->encodeCoeffNxN( TUIterator, currentCoefficients, compID ); currCompBits = m_pcEntropyCoder->getNumberOfWrittenBits(); pcResiCurrComp = m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ); m_pcTrQuant->invTransformNxN( TUIterator, compID, pcResiCurrComp, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID), currentCoefficients, cQP DEBUG_STRING_PASS_INTO_OPTIONAL(&sSingleStringTest, (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask)) ); if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction(TUIterator, compID, pLumaResi, m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), tuCompRect.width, tuCompRect.height, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(COMPONENT_Y), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID ), true); } currCompDist = m_pcRdCost->getDistPart( channelBitDepth, m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID), pcResi->getAddrPix( compID, tuCompRect.x0, tuCompRect.y0 ), pcResi->getStride(compID), tuCompRect.width, tuCompRect.height, compID); currCompCost = m_pcRdCost->calcRdCost(currCompBits, currCompDist); if (pcCU->isLosslessCoded(0)) { nonCoeffCost = MAX_DOUBLE; } } else if ((transformSkipModeId == 1) && !bUseCrossCPrediction) { currCompCost = MAX_DOUBLE; } else { currCompBits = nonCoeffBits; currCompDist = nonCoeffDist; currCompCost = nonCoeffCost; } // evaluate if ((currCompCost < minCost[compID][subTUIndex]) || ((transformSkipModeId == 1) && (currCompCost == minCost[compID][subTUIndex]))) { bestExplicitRdpcmModeUnSplit[compID][subTUIndex] = pcCU->getExplicitRdpcmMode(compID, subTUAbsPartIdx); if(isFirstMode) //check for forced null { if((nonCoeffCost < currCompCost) || (currAbsSum == 0)) { memset(currentCoefficients, 0, (sizeof(TCoeff) * tuCompRect.width * tuCompRect.height)); currAbsSum = 0; currCompBits = nonCoeffBits; currCompDist = nonCoeffDist; currCompCost = nonCoeffCost; } } #if DEBUG_STRING if (currAbsSum > 0) { DEBUG_STRING_SWAP(sSingleStringComp[compID], sSingleStringTest) } else { sSingleStringComp[compID].clear(); } #endif uiAbsSum [compID][subTUIndex] = currAbsSum; uiSingleDistComp [compID][subTUIndex] = currCompDist; minCost [compID][subTUIndex] = currCompCost; uiBestTransformMode [compID][subTUIndex] = transformSkipModeId; bestCrossCPredictionAlpha[compID][subTUIndex] = (crossCPredictionModeId == 1) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : 0; if (uiAbsSum[compID][subTUIndex] == 0) { if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction(TUIterator, compID, pLumaResi, m_pTempPel, m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0), tuCompRect.width, tuCompRect.height, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(COMPONENT_Y), tuCompRect.width, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID), true); } else { pcResiCurrComp = m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix(compID, tuCompRect.x0, tuCompRect.y0); const UInt uiStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(compID); for(UInt uiY = 0; uiY < tuCompRect.height; uiY++) { memset(pcResiCurrComp, 0, (sizeof(Pel) * tuCompRect.width)); pcResiCurrComp += uiStride; } } } } else { // reset memcpy(currentCoefficients, bestCoeffComp, (sizeof(TCoeff) * tuCompRect.width * tuCompRect.height)); #if ADAPTIVE_QP_SELECTION memcpy(currentARLCoefficients, bestArlCoeffComp, (sizeof(TCoeff) * tuCompRect.width * tuCompRect.height)); #endif for (Int y = 0; y < tuCompRect.height; y++) { memcpy((pcResiCurrComp + (y * resiStride)), &bestResiComp[y * tuCompRect.width], (sizeof(Pel) * tuCompRect.width)); } } } } pcCU->setExplicitRdpcmModePartRange ( bestExplicitRdpcmModeUnSplit[compID][subTUIndex], compID, subTUAbsPartIdx, partIdxesPerSubTU); pcCU->setTransformSkipPartRange ( uiBestTransformMode [compID][subTUIndex], compID, subTUAbsPartIdx, partIdxesPerSubTU ); pcCU->setCbfPartRange ((((uiAbsSum [compID][subTUIndex] > 0) ? 1 : 0) << uiTrMode), compID, subTUAbsPartIdx, partIdxesPerSubTU ); pcCU->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha [compID][subTUIndex], compID, subTUAbsPartIdx, partIdxesPerSubTU ); } while (TUIterator.nextSection(rTu)); //end of sub-TU loop } // processing section } // component loop for(UInt ch = 0; ch < numValidComp; ch++) { const ComponentID compID = ComponentID(ch); if (rTu.ProcessComponentSection(compID) && (rTu.getRect(compID).width != rTu.getRect(compID).height)) { offsetSubTUCBFs(rTu, compID); //the CBFs up to now have been defined for two sub-TUs - shift them down a level and replace with the parent level CBF } } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); if( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { m_pcEntropyCoder->encodeTransformSubdivFlag( 0, 5 - uiLog2TrSize ); } for(UInt ch = 0; ch < numValidComp; ch++) { const UInt chOrderChange = ((ch + 1) == numValidComp) ? 0 : (ch + 1); const ComponentID compID=ComponentID(chOrderChange); if( rTu.ProcessComponentSection(compID) ) { m_pcEntropyCoder->encodeQtCbf( rTu, compID, true ); } } for(UInt ch = 0; ch < numValidComp; ch++) { const ComponentID compID=ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { if(isChroma(compID) && (uiAbsSum[COMPONENT_Y][0] != 0)) { m_pcEntropyCoder->encodeCrossComponentPrediction( rTu, compID ); } m_pcEntropyCoder->encodeCoeffNxN( rTu, pcCoeffCurr[compID], compID ); for (UInt subTUIndex = 0; subTUIndex < 2; subTUIndex++) { uiSingleDist += uiSingleDistComp[compID][subTUIndex]; } } } uiSingleBits = m_pcEntropyCoder->getNumberOfWrittenBits(); dSingleCost = m_pcRdCost->calcRdCost( uiSingleBits, uiSingleDist ); } // check full // code sub-blocks if( bCheckSplit ) { if( bCheckFull ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_TEST ] ); m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); } Distortion uiSubdivDist = 0; UInt uiSubdivBits = 0; Double dSubdivCost = 0.0; //save the non-split CBFs in case we need to restore them later UInt bestCBF [MAX_NUM_COMPONENT]; UInt bestsubTUCBF[MAX_NUM_COMPONENT][2]; for(UInt ch = 0; ch < numValidComp; ch++) { const ComponentID compID=ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { bestCBF[compID] = pcCU->getCbf(uiAbsPartIdx, compID, uiTrMode); const TComRectangle &tuCompRect = rTu.getRect(compID); if (tuCompRect.width != tuCompRect.height) { const UInt partIdxesPerSubTU = rTu.GetAbsPartIdxNumParts(compID) >> 1; for (UInt subTU = 0; subTU < 2; subTU++) { bestsubTUCBF[compID][subTU] = pcCU->getCbf ((uiAbsPartIdx + (subTU * partIdxesPerSubTU)), compID, subTUDepth); } } } } TComTURecurse tuRecurseChild(rTu, false); const UInt uiQPartNumSubdiv = tuRecurseChild.GetAbsPartIdxNumParts(); DEBUG_STRING_NEW(sSplitString[MAX_NUM_COMPONENT]) do { DEBUG_STRING_NEW(childString) xEstimateInterResidualQT( pcResi, dSubdivCost, uiSubdivBits, uiSubdivDist, bCheckFull ? NULL : puiZeroDist, tuRecurseChild DEBUG_STRING_PASS_INTO(childString)); #if DEBUG_STRING // split the string by component and append to the relevant output (because decoder decodes in channel order, whereas this search searches by TU-order) std::size_t lastPos=0; const std::size_t endStrng=childString.find(debug_reorder_data_inter_token[MAX_NUM_COMPONENT], lastPos); for(UInt ch = 0; ch < numValidComp; ch++) { if (lastPos!=std::string::npos && childString.find(debug_reorder_data_inter_token[ch], lastPos)==lastPos) { lastPos+=strlen(debug_reorder_data_inter_token[ch]); // skip leading string } std::size_t pos=childString.find(debug_reorder_data_inter_token[ch+1], lastPos); if (pos!=std::string::npos && pos>endStrng) { lastPos=endStrng; } sSplitString[ch]+=childString.substr(lastPos, (pos==std::string::npos)? std::string::npos : (pos-lastPos) ); lastPos=pos; } #endif } while ( tuRecurseChild.nextSection(rTu) ) ; UInt uiCbfAny=0; for(UInt ch = 0; ch < numValidComp; ch++) { UInt uiYUVCbf = 0; for( UInt ui = 0; ui < 4; ++ui ) { uiYUVCbf |= pcCU->getCbf( uiAbsPartIdx + ui * uiQPartNumSubdiv, ComponentID(ch), uiTrMode + 1 ); } UChar *pBase=pcCU->getCbf( ComponentID(ch) ); const UInt flags=uiYUVCbf << uiTrMode; for( UInt ui = 0; ui < 4 * uiQPartNumSubdiv; ++ui ) { pBase[uiAbsPartIdx + ui] |= flags; } uiCbfAny|=uiYUVCbf; } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // when compID isn't a channel, code Cbfs: xEncodeInterResidualQT( MAX_NUM_COMPONENT, rTu ); for(UInt ch = 0; ch < numValidComp; ch++) { xEncodeInterResidualQT( ComponentID(ch), rTu ); } uiSubdivBits = m_pcEntropyCoder->getNumberOfWrittenBits(); dSubdivCost = m_pcRdCost->calcRdCost( uiSubdivBits, uiSubdivDist ); if (!bCheckFull || (uiCbfAny && (dSubdivCost < dSingleCost))) { rdCost += dSubdivCost; ruiBits += uiSubdivBits; ruiDist += uiSubdivDist; #if DEBUG_STRING for(UInt ch = 0; ch < numValidComp; ch++) { DEBUG_STRING_APPEND(sDebug, debug_reorder_data_inter_token[ch]) DEBUG_STRING_APPEND(sDebug, sSplitString[ch]) } #endif } else { rdCost += dSingleCost; ruiBits += uiSingleBits; ruiDist += uiSingleDist; //restore state to unsplit pcCU->setTrIdxSubParts( uiTrMode, uiAbsPartIdx, uiDepth ); for(UInt ch = 0; ch < numValidComp; ch++) { const ComponentID compID=ComponentID(ch); DEBUG_STRING_APPEND(sDebug, debug_reorder_data_inter_token[ch]) if (rTu.ProcessComponentSection(compID)) { DEBUG_STRING_APPEND(sDebug, sSingleStringComp[compID]) const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height; const UInt numberOfSections = splitIntoSubTUs ? 2 : 1; const UInt partIdxesPerSubTU = rTu.GetAbsPartIdxNumParts(compID) >> (splitIntoSubTUs ? 1 : 0); for (UInt subTUIndex = 0; subTUIndex < numberOfSections; subTUIndex++) { const UInt uisubTUPartIdx = uiAbsPartIdx + (subTUIndex * partIdxesPerSubTU); if (splitIntoSubTUs) { const UChar combinedCBF = (bestsubTUCBF[compID][subTUIndex] << subTUDepth) | (bestCBF[compID] << uiTrMode); pcCU->setCbfPartRange(combinedCBF, compID, uisubTUPartIdx, partIdxesPerSubTU); } else { pcCU->setCbfPartRange((bestCBF[compID] << uiTrMode), compID, uisubTUPartIdx, partIdxesPerSubTU); } pcCU->setCrossComponentPredictionAlphaPartRange(bestCrossCPredictionAlpha[compID][subTUIndex], compID, uisubTUPartIdx, partIdxesPerSubTU); pcCU->setTransformSkipPartRange(uiBestTransformMode[compID][subTUIndex], compID, uisubTUPartIdx, partIdxesPerSubTU); pcCU->setExplicitRdpcmModePartRange(bestExplicitRdpcmModeUnSplit[compID][subTUIndex], compID, uisubTUPartIdx, partIdxesPerSubTU); } } } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_TEST ] ); } } else { rdCost += dSingleCost; ruiBits += uiSingleBits; ruiDist += uiSingleDist; #if DEBUG_STRING for(UInt ch = 0; ch < numValidComp; ch++) { const ComponentID compID=ComponentID(ch); DEBUG_STRING_APPEND(sDebug, debug_reorder_data_inter_token[compID]) if (rTu.ProcessComponentSection(compID)) { DEBUG_STRING_APPEND(sDebug, sSingleStringComp[compID]) } } #endif } DEBUG_STRING_APPEND(sDebug, debug_reorder_data_inter_token[MAX_NUM_COMPONENT]) } Void TEncSearch::xEncodeInterResidualQT( const ComponentID compID, TComTU &rTu ) { TComDataCU* pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const UInt uiCurrTrMode = rTu.GetTransformDepthRel(); assert( pcCU->getDepth( 0 ) == pcCU->getDepth( uiAbsPartIdx ) ); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); const Bool bSubdiv = uiCurrTrMode != uiTrMode; const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); if (compID==MAX_NUM_COMPONENT) // we are not processing a channel, instead we always recurse and code the CBFs { if( uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() && uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { if((pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) && (pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N)) { assert(bSubdiv); // Inferred splitting rule - see derivation and use of interSplitFlag in the specification. } else { m_pcEntropyCoder->encodeTransformSubdivFlag( bSubdiv, 5 - uiLog2TrSize ); } } assert( !pcCU->isIntra(uiAbsPartIdx) ); const Bool bFirstCbfOfCU = uiCurrTrMode == 0; for (UInt ch=COMPONENT_Cb; chgetPic()->getNumberValidComponents(); ch++) { const ComponentID compIdInner=ComponentID(ch); if( bFirstCbfOfCU || rTu.ProcessingAllQuadrants(compIdInner) ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, compIdInner, uiCurrTrMode - 1 ) ) { m_pcEntropyCoder->encodeQtCbf( rTu, compIdInner, !bSubdiv ); } } else { assert( pcCU->getCbf( uiAbsPartIdx, compIdInner, uiCurrTrMode ) == pcCU->getCbf( uiAbsPartIdx, compIdInner, uiCurrTrMode - 1 ) ); } } if (!bSubdiv) { m_pcEntropyCoder->encodeQtCbf( rTu, COMPONENT_Y, true ); } } if( !bSubdiv ) { if (compID != MAX_NUM_COMPONENT) // we have already coded the CBFs, so now we code coefficients { if (rTu.ProcessComponentSection(compID)) { if (isChroma(compID) && (pcCU->getCbf(uiAbsPartIdx, COMPONENT_Y, uiTrMode) != 0)) { m_pcEntropyCoder->encodeCrossComponentPrediction(rTu, compID); } if (pcCU->getCbf(uiAbsPartIdx, compID, uiTrMode) != 0) { const UInt uiQTTempAccessLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; TCoeff *pcCoeffCurr = m_ppcQTTempCoeff[compID][uiQTTempAccessLayer] + rTu.getCoefficientOffset(compID); m_pcEntropyCoder->encodeCoeffNxN( rTu, pcCoeffCurr, compID ); } } } } else { if( compID==MAX_NUM_COMPONENT || pcCU->getCbf( uiAbsPartIdx, compID, uiCurrTrMode ) ) { TComTURecurse tuRecurseChild(rTu, false); do { xEncodeInterResidualQT( compID, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } } } Void TEncSearch::xSetInterResidualQTData( TComYuv* pcResi, Bool bSpatial, TComTU &rTu ) // TODO: turn this into two functions for bSpatial=true and false. { TComDataCU* pcCU=rTu.getCU(); const UInt uiCurrTrMode=rTu.GetTransformDepthRel(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); assert( pcCU->getDepth( 0 ) == pcCU->getDepth( uiAbsPartIdx ) ); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); const TComSPS *sps=pcCU->getSlice()->getSPS(); if( uiCurrTrMode == uiTrMode ) { const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const UInt uiQTTempAccessLayer = sps->getQuadtreeTULog2MaxSize() - uiLog2TrSize; if( bSpatial ) { // Data to be copied is in the spatial domain, i.e., inverse-transformed. for(UInt i=0; igetNumberValidComponents(); i++) { const ComponentID compID=ComponentID(i); if (rTu.ProcessComponentSection(compID)) { const TComRectangle &rectCompTU(rTu.getRect(compID)); m_pcQTTempTComYuv[uiQTTempAccessLayer].copyPartToPartComponentMxN ( compID, pcResi, rectCompTU ); } } } else { for (UInt ch=0; ch < getNumberValidComponents(sps->getChromaFormatIdc()); ch++) { const ComponentID compID = ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { const TComRectangle &rectCompTU(rTu.getRect(compID)); const UInt numCoeffInBlock = rectCompTU.width * rectCompTU.height; const UInt offset = rTu.getCoefficientOffset(compID); TCoeff* dest = pcCU->getCoeff(compID) + offset; const TCoeff* src = m_ppcQTTempCoeff[compID][uiQTTempAccessLayer] + offset; ::memcpy( dest, src, sizeof(TCoeff)*numCoeffInBlock ); #if ADAPTIVE_QP_SELECTION TCoeff* pcArlCoeffSrc = m_ppcQTTempArlCoeff[compID][uiQTTempAccessLayer] + offset; TCoeff* pcArlCoeffDst = pcCU->getArlCoeff(compID) + offset; ::memcpy( pcArlCoeffDst, pcArlCoeffSrc, sizeof( TCoeff ) * numCoeffInBlock ); #endif } } } } else { TComTURecurse tuRecurseChild(rTu, false); do { xSetInterResidualQTData( pcResi, bSpatial, tuRecurseChild ); } while (tuRecurseChild.nextSection(rTu)); } } UInt TEncSearch::xModeBitsIntra( TComDataCU* pcCU, UInt uiMode, UInt uiPartOffset, UInt uiDepth, const ChannelType chType ) { // Reload only contexts required for coding intra mode information m_pcRDGoOnSbacCoder->loadIntraDirMode( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST], chType ); // Temporarily set the intra dir being tested, and only // for absPartIdx, since encodeIntraDirModeLuma/Chroma only use // the entry at absPartIdx. UChar &rIntraDirVal=pcCU->getIntraDir( chType )[uiPartOffset]; UChar origVal=rIntraDirVal; rIntraDirVal = uiMode; //pcCU->setIntraDirSubParts ( chType, uiMode, uiPartOffset, uiDepth + uiInitTrDepth ); m_pcEntropyCoder->resetBits(); if (isLuma(chType)) { m_pcEntropyCoder->encodeIntraDirModeLuma ( pcCU, uiPartOffset); } else { m_pcEntropyCoder->encodeIntraDirModeChroma ( pcCU, uiPartOffset); } rIntraDirVal = origVal; // restore return m_pcEntropyCoder->getNumberOfWrittenBits(); } UInt TEncSearch::xUpdateCandList( UInt uiMode, Double uiCost, UInt uiFastCandNum, UInt * CandModeList, Double * CandCostList ) { UInt i; UInt shift=0; while ( shiftgetMergeFlag( 0 ) && pcCU->getPartitionSize( 0 ) == SIZE_2Nx2N && !pcCU->getQtRootCbf( 0 )) { pcCU->setSkipFlagSubParts( true, 0, pcCU->getDepth(0) ); m_pcEntropyCoder->resetBits(); if(pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag(pcCU, 0, true); } m_pcEntropyCoder->encodeSkipFlag(pcCU, 0, true); m_pcEntropyCoder->encodeMergeIndex(pcCU, 0, true); ruiBits += m_pcEntropyCoder->getNumberOfWrittenBits(); } else { m_pcEntropyCoder->resetBits(); if(pcCU->getSlice()->getPPS()->getTransquantBypassEnabledFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag(pcCU, 0, true); } m_pcEntropyCoder->encodeSkipFlag ( pcCU, 0, true ); m_pcEntropyCoder->encodePredMode( pcCU, 0, true ); m_pcEntropyCoder->encodePartSize( pcCU, 0, pcCU->getDepth(0), true ); m_pcEntropyCoder->encodePredInfo( pcCU, 0 ); Bool codeDeltaQp = false; Bool codeChromaQpAdj = false; m_pcEntropyCoder->encodeCoeff ( pcCU, 0, pcCU->getDepth(0), codeDeltaQp, codeChromaQpAdj ); ruiBits += m_pcEntropyCoder->getNumberOfWrittenBits(); } } /** * \brief Generate half-sample interpolated block * * \param pattern Reference picture ROI * \param biPred Flag indicating whether block is for biprediction */ Void TEncSearch::xExtDIFUpSamplingH( TComPattern* pattern ) { Int width = pattern->getROIYWidth(); Int height = pattern->getROIYHeight(); Int srcStride = pattern->getPatternLStride(); Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y); Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y); Pel *intPtr; Pel *dstPtr; Int filterSize = NTAPS_LUMA; Int halfFilterSize = (filterSize>>1); Pel *srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1; const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat(); m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 0, false, chFmt, pattern->getBitDepthY()); m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 2, false, chFmt, pattern->getBitDepthY()); intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + halfFilterSize * intStride + 1; dstPtr = m_filteredBlock[0][0].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+0, height+0, 0, false, true, chFmt, pattern->getBitDepthY()); intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1; dstPtr = m_filteredBlock[2][0].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+0, height+1, 2, false, true, chFmt, pattern->getBitDepthY()); intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + halfFilterSize * intStride; dstPtr = m_filteredBlock[0][2].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+1, height+0, 0, false, true, chFmt, pattern->getBitDepthY()); intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[2][2].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+1, height+1, 2, false, true, chFmt, pattern->getBitDepthY()); } /** * \brief Generate quarter-sample interpolated blocks * * \param pattern Reference picture ROI * \param halfPelRef Half-pel mv * \param biPred Flag indicating whether block is for biprediction */ Void TEncSearch::xExtDIFUpSamplingQ( TComPattern* pattern, TComMv halfPelRef ) { Int width = pattern->getROIYWidth(); Int height = pattern->getROIYHeight(); Int srcStride = pattern->getPatternLStride(); Pel *srcPtr; Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y); Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y); Pel *intPtr; Pel *dstPtr; Int filterSize = NTAPS_LUMA; Int halfFilterSize = (filterSize>>1); Int extHeight = (halfPelRef.getVer() == 0) ? height + filterSize : height + filterSize-1; const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat(); // Horizontal filter 1/4 srcPtr = pattern->getROIY() - halfFilterSize * srcStride - 1; intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y); if (halfPelRef.getVer() > 0) { srcPtr += srcStride; } if (halfPelRef.getHor() >= 0) { srcPtr += 1; } m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 1, false, chFmt, pattern->getBitDepthY()); // Horizontal filter 3/4 srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1; intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y); if (halfPelRef.getVer() > 0) { srcPtr += srcStride; } if (halfPelRef.getHor() > 0) { srcPtr += 1; } m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 3, false, chFmt, pattern->getBitDepthY()); // Generate @ 1,1 intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[1][1].getAddr(COMPONENT_Y); if (halfPelRef.getVer() == 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 3,1 intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[3][1].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY()); if (halfPelRef.getVer() != 0) { // Generate @ 2,1 intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[2][1].getAddr(COMPONENT_Y); if (halfPelRef.getVer() == 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 2,3 intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[2][3].getAddr(COMPONENT_Y); if (halfPelRef.getVer() == 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, pattern->getBitDepthY()); } else { // Generate @ 0,1 intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + halfFilterSize * intStride; dstPtr = m_filteredBlock[0][1].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 0,3 intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + halfFilterSize * intStride; dstPtr = m_filteredBlock[0][3].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, pattern->getBitDepthY()); } if (halfPelRef.getHor() != 0) { // Generate @ 1,2 intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[1][2].getAddr(COMPONENT_Y); if (halfPelRef.getHor() > 0) { intPtr += 1; } if (halfPelRef.getVer() >= 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 3,2 intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[3][2].getAddr(COMPONENT_Y); if (halfPelRef.getHor() > 0) { intPtr += 1; } if (halfPelRef.getVer() > 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY()); } else { // Generate @ 1,0 intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1; dstPtr = m_filteredBlock[1][0].getAddr(COMPONENT_Y); if (halfPelRef.getVer() >= 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 3,0 intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1; dstPtr = m_filteredBlock[3][0].getAddr(COMPONENT_Y); if (halfPelRef.getVer() > 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY()); } // Generate @ 1,3 intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[1][3].getAddr(COMPONENT_Y); if (halfPelRef.getVer() == 0) { intPtr += intStride; } m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY()); // Generate @ 3,3 intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride; dstPtr = m_filteredBlock[3][3].getAddr(COMPONENT_Y); m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY()); } //! set wp tables Void TEncSearch::setWpScalingDistParam( TComDataCU* pcCU, Int iRefIdx, RefPicList eRefPicListCur ) { if ( iRefIdx<0 ) { m_cDistParam.bApplyWeight = false; return; } TComSlice *pcSlice = pcCU->getSlice(); WPScalingParam *wp0 , *wp1; m_cDistParam.bApplyWeight = ( pcSlice->getSliceType()==P_SLICE && pcSlice->testWeightPred() ) || ( pcSlice->getSliceType()==B_SLICE && pcSlice->testWeightBiPred() ) ; if ( !m_cDistParam.bApplyWeight ) { return; } Int iRefIdx0 = ( eRefPicListCur == REF_PIC_LIST_0 ) ? iRefIdx : (-1); Int iRefIdx1 = ( eRefPicListCur == REF_PIC_LIST_1 ) ? iRefIdx : (-1); getWpScaling( pcCU, iRefIdx0, iRefIdx1, wp0 , wp1 ); if ( iRefIdx0 < 0 ) { wp0 = NULL; } if ( iRefIdx1 < 0 ) { wp1 = NULL; } m_cDistParam.wpCur = NULL; if ( eRefPicListCur == REF_PIC_LIST_0 ) { m_cDistParam.wpCur = wp0; } else { m_cDistParam.wpCur = wp1; } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncSearch.h000066400000000000000000000556721442026013100205500ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSearch.h \brief encoder search class (header) */ #ifndef __TENCSEARCH__ #define __TENCSEARCH__ // Include files #include "TLibCommon/TComYuv.h" #include "TLibCommon/TComMotionInfo.h" #include "TLibCommon/TComPattern.h" #include "TLibCommon/TComPrediction.h" #include "TLibCommon/TComTrQuant.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComRectangle.h" #include "TEncEntropy.h" #include "TEncSbac.h" #include "TEncCfg.h" //! \ingroup TLibEncoder //! \{ class TEncCu; // ==================================================================================================================== // Class definition // ==================================================================================================================== static const UInt MAX_NUM_REF_LIST_ADAPT_SR=2; static const UInt MAX_IDX_ADAPT_SR=33; static const UInt NUM_MV_PREDICTORS=3; /// encoder search class class TEncSearch : public TComPrediction { private: TCoeff** m_ppcQTTempCoeff[MAX_NUM_COMPONENT /* 0->Y, 1->Cb, 2->Cr*/]; #if ADAPTIVE_QP_SELECTION TCoeff** m_ppcQTTempArlCoeff[MAX_NUM_COMPONENT]; #endif UChar* m_puhQTTempTrIdx; UChar* m_puhQTTempCbf[MAX_NUM_COMPONENT]; TComYuv* m_pcQTTempTComYuv; TComYuv m_tmpYuvPred; // To be used in xGetInterPredictionError() to avoid constant memory allocation/deallocation SChar* m_phQTTempCrossComponentPredictionAlpha[MAX_NUM_COMPONENT]; Pel* m_pSharedPredTransformSkip[MAX_NUM_COMPONENT]; TCoeff* m_pcQTTempTUCoeff[MAX_NUM_COMPONENT]; UChar* m_puhQTTempTransformSkipFlag[MAX_NUM_COMPONENT]; TComYuv m_pcQTTempTransformSkipTComYuv; #if ADAPTIVE_QP_SELECTION TCoeff* m_ppcQTTempTUArlCoeff[MAX_NUM_COMPONENT]; #endif protected: // interface to option TEncCfg* m_pcEncCfg; // interface to classes TComTrQuant* m_pcTrQuant; TComRdCost* m_pcRdCost; TEncEntropy* m_pcEntropyCoder; // ME parameters Int m_iSearchRange; Int m_bipredSearchRange; // Search range for bi-prediction MESearchMethod m_motionEstimationSearchMethod; Int m_aaiAdaptSR[MAX_NUM_REF_LIST_ADAPT_SR][MAX_IDX_ADAPT_SR]; TComMv m_acMvPredictors[NUM_MV_PREDICTORS]; // Left, Above, AboveRight. enum MVP_DIR first NUM_MV_PREDICTORS entries are suitable for accessing. // RD computation TEncSbac*** m_pppcRDSbacCoder; TEncSbac* m_pcRDGoOnSbacCoder; DistParam m_cDistParam; // Misc. Pel* m_pTempPel; // AMVP cost computation // UInt m_auiMVPIdxCost[AMVP_MAX_NUM_CANDS+1][AMVP_MAX_NUM_CANDS]; UInt m_auiMVPIdxCost[AMVP_MAX_NUM_CANDS+1][AMVP_MAX_NUM_CANDS+1]; //th array bounds TComMv m_integerMv2Nx2N[NUM_REF_PIC_LIST_01][MAX_NUM_REF]; Bool m_isInitialized; public: TEncSearch(); virtual ~TEncSearch(); Void init(TEncCfg* pcEncCfg, TComTrQuant* pcTrQuant, Int iSearchRange, Int bipredSearchRange, MESearchMethod motionEstimationSearchMethod, const UInt maxCUWidth, const UInt maxCUHeight, const UInt maxTotalCUDepth, TEncEntropy* pcEntropyCoder, TComRdCost* pcRdCost, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder ); Void destroy(); protected: /// sub-function for motion vector refinement used in fractional-pel accuracy Distortion xPatternRefinement( TComPattern* pcPatternKey, TComMv baseRefMv, Int iFrac, TComMv& rcMvFrac, Bool bAllowUseOfHadamard ); typedef struct { const Pel* piRefY; Int iYStride; Int iBestX; Int iBestY; UInt uiBestRound; UInt uiBestDistance; Distortion uiBestSad; UChar ucPointNr; } IntTZSearchStruct; // sub-functions for ME __inline Void xTZSearchHelp ( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const Int iSearchX, const Int iSearchY, const UChar ucPointNr, const UInt uiDistance ); __inline Void xTZ2PointSearch ( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB ); __inline Void xTZ8PointSquareSearch ( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, const Int iStartX, const Int iStartY, const Int iDist ); __inline Void xTZ8PointDiamondSearch( const TComPattern* const pcPatternKey, IntTZSearchStruct& rcStruct, const TComMv* const pcMvSrchRngLT, const TComMv* const pcMvSrchRngRB, const Int iStartX, const Int iStartY, const Int iDist, const Bool bCheckCornersAtDist1 ); Void xGetInterPredictionError( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPartIdx, Distortion& ruiSAD, Bool Hadamard ); public: Void estIntraPredLumaQT ( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE] DEBUG_STRING_FN_DECLARE(sDebug)); Void estIntraPredChromaQT ( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE] DEBUG_STRING_FN_DECLARE(sDebug)); /// encoder estimation - inter prediction (non-skip) Void predInterSearch ( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseRes = false #if AMP_MRG ,Bool bUseMRG = false #endif ); /// encode residual and compute rd-cost for inter mode Void encodeResAndCalcRdInterCU( TComDataCU* pcCU, TComYuv* pcYuvOrg, TComYuv* pcYuvPred, TComYuv* pcYuvResi, TComYuv* pcYuvResiBest, TComYuv* pcYuvRec, Bool bSkipResidual DEBUG_STRING_FN_DECLARE(sDebug) ); /// set ME search range Void setAdaptiveSearchRange ( Int iDir, Int iRefIdx, Int iSearchRange) { assert(iDir < MAX_NUM_REF_LIST_ADAPT_SR && iRefIdx //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TEncSlice::TEncSlice() : m_encCABACTableIdx(I_SLICE) { } TEncSlice::~TEncSlice() { destroy(); } Void TEncSlice::create( Int iWidth, Int iHeight, ChromaFormat chromaFormat, UInt iMaxCUWidth, UInt iMaxCUHeight, UChar uhTotalDepth ) { // create prediction picture m_picYuvPred.create( iWidth, iHeight, chromaFormat, iMaxCUWidth, iMaxCUHeight, uhTotalDepth, true ); // create residual picture m_picYuvResi.create( iWidth, iHeight, chromaFormat, iMaxCUWidth, iMaxCUHeight, uhTotalDepth, true ); } Void TEncSlice::destroy() { m_picYuvPred.destroy(); m_picYuvResi.destroy(); // free lambda and QP arrays m_vdRdPicLambda.clear(); m_vdRdPicQp.clear(); m_viRdPicQp.clear(); } Void TEncSlice::init( TEncTop* pcEncTop ) { m_pcCfg = pcEncTop; m_pcListPic = pcEncTop->getListPic(); m_pcGOPEncoder = pcEncTop->getGOPEncoder(); m_pcCuEncoder = pcEncTop->getCuEncoder(); m_pcPredSearch = pcEncTop->getPredSearch(); m_pcEntropyCoder = pcEncTop->getEntropyCoder(); m_pcSbacCoder = pcEncTop->getSbacCoder(); m_pcBinCABAC = pcEncTop->getBinCABAC(); m_pcTrQuant = pcEncTop->getTrQuant(); m_pcRdCost = pcEncTop->getRdCost(); m_pppcRDSbacCoder = pcEncTop->getRDSbacCoder(); m_pcRDGoOnSbacCoder = pcEncTop->getRDGoOnSbacCoder(); // create lambda and QP arrays m_vdRdPicLambda.resize(m_pcCfg->getDeltaQpRD() * 2 + 1 ); m_vdRdPicQp.resize( m_pcCfg->getDeltaQpRD() * 2 + 1 ); m_viRdPicQp.resize( m_pcCfg->getDeltaQpRD() * 2 + 1 ); m_pcRateCtrl = pcEncTop->getRateCtrl(); } Void TEncSlice::updateLambda(TComSlice* pSlice, Double dQP) { Int iQP = (Int)dQP; Double dLambda = calculateLambda(pSlice, m_gopID, pSlice->getDepth(), pSlice->getSliceQp(), dQP, iQP); setUpLambda(pSlice, dLambda, iQP); } Void TEncSlice::setUpLambda(TComSlice* slice, const Double dLambda, Int iQP) { // store lambda m_pcRdCost ->setLambda( dLambda, slice->getSPS()->getBitDepths() ); // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma. Double dLambdas[MAX_NUM_COMPONENT] = { dLambda }; for(UInt compIdx=1; compIdxgetPPS()->getQpOffset(compID) + slice->getSliceChromaQpDelta(compID); Int qpc=(iQP + chromaQPOffset < 0) ? iQP : getScaledChromaQP(iQP + chromaQPOffset, m_pcCfg->getChromaFormatIdc()); Double tmpWeight = pow( 2.0, (iQP-qpc)/3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset m_pcRdCost->setDistortionWeight(compID, tmpWeight); dLambdas[compIdx]=dLambda/tmpWeight; } #if RDOQ_CHROMA_LAMBDA // for RDOQ m_pcTrQuant->setLambdas( dLambdas ); #else m_pcTrQuant->setLambda( dLambda ); #endif // For SAO slice->setLambdas( dLambdas ); } /** - non-referenced frame marking - QP computation based on temporal structure - lambda computation based on QP - set temporal layer ID and the parameter sets . \param pcPic picture class \param pocLast POC of last picture \param pocCurr current POC \param iNumPicRcvd number of received pictures \param iGOPid POC offset for hierarchical structure \param rpcSlice slice header class \param isField true for field coding */ Void TEncSlice::initEncSlice( TComPic* pcPic, const Int pocLast, const Int pocCurr, const Int iGOPid, TComSlice*& rpcSlice, const Bool isField ) { Double dQP; Double dLambda; rpcSlice = pcPic->getSlice(0); rpcSlice->setSliceBits(0); rpcSlice->setPic( pcPic ); rpcSlice->initSlice(); rpcSlice->setPicOutputFlag( true ); rpcSlice->setPOC( pocCurr ); pcPic->setField(isField); m_gopID = iGOPid; // depth computation based on GOP size Int depth; { Int poc = rpcSlice->getPOC(); if(isField) { poc = (poc/2) % (m_pcCfg->getGOPSize()/2); } else { poc = poc % m_pcCfg->getGOPSize(); } if ( poc == 0 ) { depth = 0; } else { Int step = m_pcCfg->getGOPSize(); depth = 0; for( Int i=step>>1; i>=1; i>>=1 ) { for ( Int j=i; jgetGOPSize(); j+=step ) { if ( j == poc ) { i=0; break; } } step >>= 1; depth++; } } if(m_pcCfg->getHarmonizeGopFirstFieldCoupleEnabled() && poc != 0) { if (isField && ((rpcSlice->getPOC() % 2) == 1)) { depth ++; } } } // slice type SliceType eSliceType; eSliceType=B_SLICE; if(!(isField && pocLast == 1) || !m_pcCfg->getEfficientFieldIRAPEnabled()) { if(m_pcCfg->getDecodingRefreshType() == 3) { eSliceType = (pocLast == 0 || pocCurr % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType; } else { eSliceType = (pocLast == 0 || (pocCurr - (isField ? 1 : 0)) % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType; } } rpcSlice->setSliceType ( eSliceType ); // ------------------------------------------------------------------------------------------------------------------ // Non-referenced frame marking // ------------------------------------------------------------------------------------------------------------------ if(pocLast == 0) { rpcSlice->setTemporalLayerNonReferenceFlag(false); } else { rpcSlice->setTemporalLayerNonReferenceFlag(!m_pcCfg->getGOPEntry(iGOPid).m_refPic); } rpcSlice->setReferenced(true); // ------------------------------------------------------------------------------------------------------------------ // QP setting // ------------------------------------------------------------------------------------------------------------------ dQP = m_pcCfg->getQPForPicture(iGOPid, rpcSlice); // ------------------------------------------------------------------------------------------------------------------ // Lambda computation // ------------------------------------------------------------------------------------------------------------------ const Int temporalId=m_pcCfg->getGOPEntry(iGOPid).m_temporalId; Int iQP; Double dOrigQP = dQP; // pre-compute lambda and QP values for all possible QP candidates for ( Int iDQpIdx = 0; iDQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; iDQpIdx++ ) { // compute QP value dQP = dOrigQP + ((iDQpIdx+1)>>1)*(iDQpIdx%2 ? -1 : 1); dLambda = calculateLambda(rpcSlice, iGOPid, depth, dQP, dQP, iQP ); m_vdRdPicLambda[iDQpIdx] = dLambda; m_vdRdPicQp [iDQpIdx] = dQP; m_viRdPicQp [iDQpIdx] = iQP; } // obtain dQP = 0 case dLambda = m_vdRdPicLambda[0]; dQP = m_vdRdPicQp [0]; iQP = m_viRdPicQp [0]; if(rpcSlice->getPPS()->getSliceChromaQpFlag()) { const Bool bUseIntraOrPeriodicOffset = rpcSlice->getSliceType()==I_SLICE || (m_pcCfg->getSliceChromaOffsetQpPeriodicity()!=0 && (rpcSlice->getPOC()%m_pcCfg->getSliceChromaOffsetQpPeriodicity())==0); Int cbQP = bUseIntraOrPeriodicOffset? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(false) : m_pcCfg->getGOPEntry(iGOPid).m_CbQPoffset; Int crQP = bUseIntraOrPeriodicOffset? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(true) : m_pcCfg->getGOPEntry(iGOPid).m_CrQPoffset; cbQP = Clip3( -12, 12, cbQP + rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb) ) - rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb); crQP = Clip3( -12, 12, crQP + rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr) ) - rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr); rpcSlice->setSliceChromaQpDelta(COMPONENT_Cb, Clip3( -12, 12, cbQP)); assert(rpcSlice->getSliceChromaQpDelta(COMPONENT_Cb)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb)<=12 && rpcSlice->getSliceChromaQpDelta(COMPONENT_Cb)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb)>=-12); rpcSlice->setSliceChromaQpDelta(COMPONENT_Cr, Clip3( -12, 12, crQP)); assert(rpcSlice->getSliceChromaQpDelta(COMPONENT_Cr)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr)<=12 && rpcSlice->getSliceChromaQpDelta(COMPONENT_Cr)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr)>=-12); } else { rpcSlice->setSliceChromaQpDelta( COMPONENT_Cb, 0 ); rpcSlice->setSliceChromaQpDelta( COMPONENT_Cr, 0 ); } setUpLambda(rpcSlice, dLambda, iQP); if (m_pcCfg->getFastMEForGenBLowDelayEnabled()) { // restore original slice type if(!(isField && pocLast == 1) || !m_pcCfg->getEfficientFieldIRAPEnabled()) { if(m_pcCfg->getDecodingRefreshType() == 3) { eSliceType = (pocLast == 0 || (pocCurr) % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType; } else { eSliceType = (pocLast == 0 || (pocCurr - (isField ? 1 : 0)) % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType; } } rpcSlice->setSliceType ( eSliceType ); } if (m_pcCfg->getUseRecalculateQPAccordingToLambda()) { dQP = xGetQPValueAccordingToLambda( dLambda ); iQP = max( -rpcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), min( MAX_QP, (Int) floor( dQP + 0.5 ) ) ); } rpcSlice->setSliceQp ( iQP ); #if ADAPTIVE_QP_SELECTION rpcSlice->setSliceQpBase ( iQP ); #endif rpcSlice->setSliceQpDelta ( 0 ); rpcSlice->setUseChromaQpAdj( rpcSlice->getPPS()->getPpsRangeExtension().getChromaQpOffsetListEnabledFlag() ); rpcSlice->setNumRefIdx(REF_PIC_LIST_0,m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive); rpcSlice->setNumRefIdx(REF_PIC_LIST_1,m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive); if ( m_pcCfg->getDeblockingFilterMetric() ) { rpcSlice->setDeblockingFilterOverrideFlag(true); rpcSlice->setDeblockingFilterDisable(false); rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 ); rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 ); } else if (rpcSlice->getPPS()->getDeblockingFilterControlPresentFlag()) { rpcSlice->setDeblockingFilterOverrideFlag( rpcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() ); rpcSlice->setDeblockingFilterDisable( rpcSlice->getPPS()->getPPSDeblockingFilterDisabledFlag() ); if ( !rpcSlice->getDeblockingFilterDisable()) { if ( rpcSlice->getDeblockingFilterOverrideFlag() && eSliceType!=I_SLICE) { rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_betaOffsetDiv2 + m_pcCfg->getLoopFilterBetaOffset() ); rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_tcOffsetDiv2 + m_pcCfg->getLoopFilterTcOffset() ); } else { rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getLoopFilterBetaOffset() ); rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getLoopFilterTcOffset() ); } } } else { rpcSlice->setDeblockingFilterOverrideFlag( false ); rpcSlice->setDeblockingFilterDisable( false ); rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 ); rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 ); } rpcSlice->setDepth ( depth ); pcPic->setTLayer( temporalId ); if(eSliceType==I_SLICE) { pcPic->setTLayer(0); } rpcSlice->setTLayer( pcPic->getTLayer() ); pcPic->setPicYuvPred( &m_picYuvPred ); pcPic->setPicYuvResi( &m_picYuvResi ); rpcSlice->setSliceMode ( m_pcCfg->getSliceMode() ); rpcSlice->setSliceArgument ( m_pcCfg->getSliceArgument() ); rpcSlice->setSliceSegmentMode ( m_pcCfg->getSliceSegmentMode() ); rpcSlice->setSliceSegmentArgument ( m_pcCfg->getSliceSegmentArgument() ); rpcSlice->setMaxNumMergeCand ( m_pcCfg->getMaxNumMergeCand() ); } Double TEncSlice::calculateLambda( const TComSlice* slice, const Int GOPid, // entry in the GOP table const Int depth, // slice GOP hierarchical depth. const Double refQP, // initial slice-level QP const Double dQP, // initial double-precision QP Int &iQP ) // returned integer QP. { enum SliceType eSliceType = slice->getSliceType(); const Bool isField = slice->getPic()->isField(); const Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 ); const Int SHIFT_QP = 12; const Int temporalId=m_pcCfg->getGOPEntry(GOPid).m_temporalId; const std::vector &intraLambdaModifiers=m_pcCfg->getIntraLambdaModifier(); #if FULL_NBIT Int bitdepth_luma_qp_scale = 6 * (slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8); #else Int bitdepth_luma_qp_scale = 0; #endif Double qp_temp = dQP + bitdepth_luma_qp_scale - SHIFT_QP; // Case #1: I or P-slices (key-frame) Double dQPFactor = m_pcCfg->getGOPEntry(GOPid).m_QPFactor; if ( eSliceType==I_SLICE ) { if (m_pcCfg->getIntraQpFactor()>=0.0 && m_pcCfg->getGOPEntry(GOPid).m_sliceType != I_SLICE) { dQPFactor=m_pcCfg->getIntraQpFactor(); } else { if(m_pcCfg->getLambdaFromQPEnable()) { dQPFactor=0.57; } else { Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)(isField ? NumberBFrames/2 : NumberBFrames) ); dQPFactor=0.57*dLambda_scale; } } } else if( m_pcCfg->getLambdaFromQPEnable() ) { dQPFactor=0.57; } Double dLambda = dQPFactor*pow( 2.0, qp_temp/3.0 ); if( !(m_pcCfg->getLambdaFromQPEnable()) && depth>0 ) { #if FULL_NBIT Double qp_temp_ref_orig = refQP - SHIFT_QP; dLambda *= Clip3( 2.00, 4.00, (qp_temp_ref_orig / 6.0) ); // (j == B_SLICE && p_cur_frm->layer != 0 ) #else Double qp_temp_ref = refQP + bitdepth_luma_qp_scale - SHIFT_QP; dLambda *= Clip3( 2.00, 4.00, (qp_temp_ref / 6.0) ); // (j == B_SLICE && p_cur_frm->layer != 0 ) #endif } // if hadamard is used in ME process if ( !m_pcCfg->getUseHADME() && slice->getSliceType( ) != I_SLICE ) { dLambda *= 0.95; } Double lambdaModifier; if( eSliceType != I_SLICE || intraLambdaModifiers.empty()) { lambdaModifier = m_pcCfg->getLambdaModifier( temporalId ); } else { lambdaModifier = intraLambdaModifiers[ (temporalId < intraLambdaModifiers.size()) ? temporalId : (intraLambdaModifiers.size()-1) ]; } dLambda *= lambdaModifier; iQP = max( -slice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), min( MAX_QP, (Int) floor( dQP + 0.5 ) ) ); // NOTE: the lambda modifiers that are sometimes applied later might be best always applied in here. return dLambda; } Void TEncSlice::resetQP( TComPic* pic, Int sliceQP, Double lambda ) { TComSlice* slice = pic->getSlice(0); // store lambda slice->setSliceQp( sliceQP ); #if ADAPTIVE_QP_SELECTION slice->setSliceQpBase ( sliceQP ); #endif setUpLambda(slice, lambda, sliceQP); } // ==================================================================================================================== // Public member functions // ==================================================================================================================== //! set adaptive search range based on poc difference Void TEncSlice::setSearchRange( TComSlice* pcSlice ) { Int iCurrPOC = pcSlice->getPOC(); Int iRefPOC; Int iGOPSize = m_pcCfg->getGOPSize(); Int iOffset = (iGOPSize >> 1); Int iMaxSR = m_pcCfg->getSearchRange(); Int iNumPredDir = pcSlice->isInterP() ? 1 : 2; for (Int iDir = 0; iDir < iNumPredDir; iDir++) { RefPicList e = ( iDir ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for (Int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(e); iRefIdx++) { iRefPOC = pcSlice->getRefPic(e, iRefIdx)->getPOC(); Int newSearchRange = Clip3(m_pcCfg->getMinSearchWindow(), iMaxSR, (iMaxSR*ADAPT_SR_SCALE*abs(iCurrPOC - iRefPOC)+iOffset)/iGOPSize); m_pcPredSearch->setAdaptiveSearchRange(iDir, iRefIdx, newSearchRange); } } } /** Multi-loop slice encoding for different slice QP \param pcPic picture class */ Void TEncSlice::precompressSlice( TComPic* pcPic ) { // if deltaQP RD is not used, simply return if ( m_pcCfg->getDeltaQpRD() == 0 ) { return; } if ( m_pcCfg->getUseRateCtrl() ) { printf( "\nMultiple QP optimization is not allowed when rate control is enabled." ); assert(0); return; } TComSlice* pcSlice = pcPic->getSlice(getSliceIdx()); if (pcSlice->getDependentSliceSegmentFlag()) { // if this is a dependent slice segment, then it was optimised // when analysing the entire slice. return; } if (pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES) { // TODO: investigate use of average cost per CTU so that this Slice Mode can be used. printf( "\nUnable to optimise Slice-level QP if Slice Mode is set to FIXED_NUMBER_OF_BYTES\n" ); assert(0); return; } Double dPicRdCostBest = MAX_DOUBLE; UInt uiQpIdxBest = 0; Double dFrameLambda; #if FULL_NBIT Int SHIFT_QP = 12 + 6 * (pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8); #else Int SHIFT_QP = 12; #endif // set frame lambda if (m_pcCfg->getGOPSize() > 1) { dFrameLambda = 0.68 * pow (2, (m_viRdPicQp[0] - SHIFT_QP) / 3.0) * (pcSlice->isInterB()? 2 : 1); } else { dFrameLambda = 0.68 * pow (2, (m_viRdPicQp[0] - SHIFT_QP) / 3.0); } m_pcRdCost ->setFrameLambda(dFrameLambda); // for each QP candidate for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ ) { pcSlice ->setSliceQp ( m_viRdPicQp [uiQpIdx] ); #if ADAPTIVE_QP_SELECTION pcSlice ->setSliceQpBase ( m_viRdPicQp [uiQpIdx] ); #endif setUpLambda(pcSlice, m_vdRdPicLambda[uiQpIdx], m_viRdPicQp [uiQpIdx]); // try compress compressSlice ( pcPic, true, m_pcCfg->getFastDeltaQp()); UInt64 uiPicDist = m_uiPicDist; // Distortion, as calculated by compressSlice. // NOTE: This distortion is the chroma-weighted SSE distortion for the slice. // Previously a standard SSE distortion was calculated (for the entire frame). // Which is correct? // TODO: Update loop filter, SAO and distortion calculation to work on one slice only. // m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist ); // compute RD cost and choose the best Double dPicRdCost = m_pcRdCost->calcRdCost( (Double)m_uiPicTotalBits, uiPicDist, DF_SSE_FRAME); if ( dPicRdCost < dPicRdCostBest ) { uiQpIdxBest = uiQpIdx; dPicRdCostBest = dPicRdCost; } } // set best values pcSlice ->setSliceQp ( m_viRdPicQp [uiQpIdxBest] ); #if ADAPTIVE_QP_SELECTION pcSlice ->setSliceQpBase ( m_viRdPicQp [uiQpIdxBest] ); #endif setUpLambda(pcSlice, m_vdRdPicLambda[uiQpIdxBest], m_viRdPicQp [uiQpIdxBest]); } Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others? { Double iSumHadSlice = 0; TComSlice * const pcSlice = pcPic->getSlice(getSliceIdx()); const TComSPS &sps = *(pcSlice->getSPS()); const Int shift = sps.getBitDepth(CHANNEL_TYPE_LUMA)-8; const Int offset = (shift>0)?(1<<(shift-1)):0; pcSlice->setSliceSegmentBits(0); UInt startCtuTsAddr, boundingCtuTsAddr; xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic ); for( UInt ctuTsAddr = startCtuTsAddr, ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr); ctuTsAddr < boundingCtuTsAddr; ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(++ctuTsAddr) ) { // initialize CU encoder TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); pCtu->initCtu( pcPic, ctuRsAddr ); Int height = min( sps.getMaxCUHeight(),sps.getPicHeightInLumaSamples() - ctuRsAddr / pcPic->getFrameWidthInCtus() * sps.getMaxCUHeight() ); Int width = min( sps.getMaxCUWidth(), sps.getPicWidthInLumaSamples() - ctuRsAddr % pcPic->getFrameWidthInCtus() * sps.getMaxCUWidth() ); Int iSumHad = m_pcCuEncoder->updateCtuDataISlice(pCtu, width, height); (m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra=(iSumHad+offset)>>shift; iSumHadSlice += (m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra; } m_pcRateCtrl->getRCPic()->setTotalIntraCost(iSumHadSlice); } /** \param pcPic picture class */ Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice, const Bool bFastDeltaQP ) { // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed, // effectively disabling the slice-segment-mode. UInt startCtuTsAddr; UInt boundingCtuTsAddr; TComSlice* const pcSlice = pcPic->getSlice(getSliceIdx()); pcSlice->setSliceSegmentBits(0); xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic ); if (bCompressEntireSlice) { boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr(); pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr); } // initialize cost values - these are used by precompressSlice (they should be parameters). m_uiPicTotalBits = 0; m_dPicRdCost = 0; // NOTE: This is a write-only variable! m_uiPicDist = 0; m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST] ); m_pcEntropyCoder->resetEntropy ( pcSlice ); TEncBinCABAC* pRDSbacCoder = (TEncBinCABAC *) m_pppcRDSbacCoder[0][CI_CURR_BEST]->getEncBinIf(); pRDSbacCoder->setBinCountingEnableFlag( false ); pRDSbacCoder->setBinsCoded( 0 ); TComBitCounter tempBitCounter; const UInt frameWidthInCtus = pcPic->getPicSym()->getFrameWidthInCtus(); m_pcCuEncoder->setFastDeltaQp(bFastDeltaQP); //------------------------------------------------------------------------------ // Weighted Prediction parameters estimation. //------------------------------------------------------------------------------ // calculate AC/DC values for current picture if( pcSlice->getPPS()->getUseWP() || pcSlice->getPPS()->getWPBiPred() ) { xCalcACDCParamSlice(pcSlice); } const Bool bWp_explicit = (pcSlice->getSliceType()==P_SLICE && pcSlice->getPPS()->getUseWP()) || (pcSlice->getSliceType()==B_SLICE && pcSlice->getPPS()->getWPBiPred()); if ( bWp_explicit ) { //------------------------------------------------------------------------------ // Weighted Prediction implemented at Slice level. SliceMode=2 is not supported yet. //------------------------------------------------------------------------------ if ( pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES || pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES ) { printf("Weighted Prediction is not supported with slice mode determined by max number of bins.\n"); exit(0); } xEstimateWPParamSlice( pcSlice, m_pcCfg->getWeightedPredictionMethod() ); pcSlice->initWpScaling(pcSlice->getSPS()); // check WP on/off xCheckWPEnable( pcSlice ); } #if ADAPTIVE_QP_SELECTION if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag())) { // TODO: this won't work with dependent slices: they do not have their own QP. Check fix to mask clause execution with && !(pcSlice->getDependentSliceSegmentFlag()) m_pcTrQuant->clearSliceARLCnt(); // TODO: this looks wrong for multiple slices - the results of all but the last slice will be cleared before they are used (all slices compressed, and then all slices encoded) if(pcSlice->getSliceType()!=I_SLICE) { Int qpBase = pcSlice->getSliceQpBase(); pcSlice->setSliceQp(qpBase + m_pcTrQuant->getQpDelta(qpBase)); } } #endif // Adjust initial state if this is the start of a dependent slice. { const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr); const UInt currentTileIdx = pcPic->getPicSym()->getTileIdxMap(ctuRsAddr); const TComTile *pCurrentTile = pcPic->getPicSym()->getTComTile(currentTileIdx); const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr(); if( pcSlice->getDependentSliceSegmentFlag() && ctuRsAddr != firstCtuRsAddrOfTile ) { // This will only occur if dependent slice-segments (m_entropyCodingSyncContextState=true) are being used. if( pCurrentTile->getTileWidthInCtus() >= 2 || !m_pcCfg->getEntropyCodingSyncEnabledFlag() ) { m_pppcRDSbacCoder[0][CI_CURR_BEST]->loadContexts( &m_lastSliceSegmentEndContextState ); } } } // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment) for( UInt ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ++ctuTsAddr ) { const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr); // initialize CTU encoder TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); pCtu->initCtu( pcPic, ctuRsAddr ); // update CABAC state const UInt firstCtuRsAddrOfTile = pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr))->getFirstCtuRsAddr(); const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus; const UInt ctuXPosInCtus = ctuRsAddr % frameWidthInCtus; if (ctuRsAddr == firstCtuRsAddrOfTile) { m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetEntropy(pcSlice); } else if ( ctuXPosInCtus == tileXPosInCtus && m_pcCfg->getEntropyCodingSyncEnabledFlag()) { // reset and then update contexts to the state at the end of the top-right CTU (if within current slice and tile). m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetEntropy(pcSlice); // Sync if the Top-Right is available. TComDataCU *pCtuUp = pCtu->getCtuAbove(); if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus) ) { TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 ); if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) ) { // Top-Right is available, we use it. m_pppcRDSbacCoder[0][CI_CURR_BEST]->loadContexts( &m_entropyCodingSyncContextState ); } } } // set go-on entropy coder (used for all trial encodings - the cu encoder and encoder search also have a copy of the same pointer) m_pcEntropyCoder->setEntropyCoder ( m_pcRDGoOnSbacCoder ); m_pcEntropyCoder->setBitstream( &tempBitCounter ); tempBitCounter.resetBits(); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[0][CI_CURR_BEST] ); // this copy is not strictly necessary here, but indicates that the GoOnSbacCoder // is reset to a known state before every decision process. ((TEncBinCABAC*)m_pcRDGoOnSbacCoder->getEncBinIf())->setBinCountingEnableFlag(true); Double oldLambda = m_pcRdCost->getLambda(); if ( m_pcCfg->getUseRateCtrl() ) { Int estQP = pcSlice->getSliceQp(); Double estLambda = -1.0; Double bpp = -1.0; if ( ( pcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() ) { estQP = pcSlice->getSliceQp(); } else { bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType()); if ( pcPic->getSlice( 0 )->getSliceType() == I_SLICE) { estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP); } else { estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp ); estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() ); } estQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, estQP ); m_pcRdCost->setLambda(estLambda, pcSlice->getSPS()->getBitDepths()); #if RDOQ_CHROMA_LAMBDA // set lambda for RDOQ const Double chromaLambda = estLambda / m_pcRdCost->getChromaWeight(); const Double lambdaArray[MAX_NUM_COMPONENT] = { estLambda, chromaLambda, chromaLambda }; m_pcTrQuant->setLambdas( lambdaArray ); #else m_pcTrQuant->setLambda( estLambda ); #endif } m_pcRateCtrl->setRCQP( estQP ); #if ADAPTIVE_QP_SELECTION pCtu->getSlice()->setSliceQpBase( estQP ); #endif } // run CTU trial encoder m_pcCuEncoder->compressCtu( pCtu ); // All CTU decisions have now been made. Restore entropy coder to an initial stage, ready to make a true encode, // which will result in the state of the contexts being correct. It will also count up the number of bits coded, // which is used if there is a limit of the number of bytes per slice-segment. m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST] ); m_pcEntropyCoder->setBitstream( &tempBitCounter ); pRDSbacCoder->setBinCountingEnableFlag( true ); m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetBits(); pRDSbacCoder->setBinsCoded( 0 ); // encode CTU and calculate the true bit counters. m_pcCuEncoder->encodeCtu( pCtu ); pRDSbacCoder->setBinCountingEnableFlag( false ); const Int numberOfWrittenBits = m_pcEntropyCoder->getNumberOfWrittenBits(); // Calculate if this CTU puts us over slice bit size. // cannot terminate if current slice/slice-segment would be 0 Ctu in size, const UInt validEndOfSliceCtuTsAddr = ctuTsAddr + (ctuTsAddr == startCtuTsAddr ? 1 : 0); // Set slice end parameter if(pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceBits()+numberOfWrittenBits > (pcSlice->getSliceArgument()<<3)) { pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); boundingCtuTsAddr=validEndOfSliceCtuTsAddr; } else if((!bCompressEntireSlice) && pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3)) { pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr); boundingCtuTsAddr=validEndOfSliceCtuTsAddr; } if (boundingCtuTsAddr <= ctuTsAddr) { break; } pcSlice->setSliceBits( (UInt)(pcSlice->getSliceBits() + numberOfWrittenBits) ); pcSlice->setSliceSegmentBits(pcSlice->getSliceSegmentBits()+numberOfWrittenBits); // Store probabilities of second CTU in line into buffer - used only if wavefront-parallel-processing is enabled. if ( ctuXPosInCtus == tileXPosInCtus+1 && m_pcCfg->getEntropyCodingSyncEnabledFlag()) { m_entropyCodingSyncContextState.loadContexts(m_pppcRDSbacCoder[0][CI_CURR_BEST]); } if ( m_pcCfg->getUseRateCtrl() ) { Int actualQP = g_RCInvalidQPValue; Double actualLambda = m_pcRdCost->getLambda(); Int actualBits = pCtu->getTotalBits(); Int numberOfEffectivePixels = 0; #if JVET_M0600_RATE_CTRL Int numberOfSkipPixel = 0; for (Int idx = 0; idx < pcPic->getNumPartitionsInCtu(); idx++) { numberOfSkipPixel += 16 * pCtu->isSkipped(idx); } #endif for ( Int idx = 0; idx < pcPic->getNumPartitionsInCtu(); idx++ ) { if ( pCtu->getPredictionMode( idx ) != NUMBER_OF_PREDICTION_MODES && ( !pCtu->isSkipped( idx ) ) ) { numberOfEffectivePixels = numberOfEffectivePixels + 16; break; } } #if JVET_M0600_RATE_CTRL Double skipRatio = (Double)numberOfSkipPixel / m_pcRateCtrl->getRCPic()->getLCU(ctuTsAddr).m_numberOfPixel; #endif if ( numberOfEffectivePixels == 0 ) { actualQP = g_RCInvalidQPValue; } else { actualQP = pCtu->getQP( 0 ); } #if JVET_K0390_RATE_CTRL m_pcRateCtrl->getRCPic()->getLCU(ctuTsAddr).m_actualMSE = (Double)pCtu->getTotalDistortion() / (Double)m_pcRateCtrl->getRCPic()->getLCU(ctuTsAddr).m_numberOfPixel; #endif m_pcRdCost->setLambda(oldLambda, pcSlice->getSPS()->getBitDepths()); #if JVET_M0600_RATE_CTRL m_pcRateCtrl->getRCPic()->updateAfterCTU(m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda, skipRatio, pCtu->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC()); #else m_pcRateCtrl->getRCPic()->updateAfterCTU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda, pCtu->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() ); #endif } m_uiPicTotalBits += pCtu->getTotalBits(); m_dPicRdCost += pCtu->getTotalCost(); m_uiPicDist += pCtu->getTotalDistortion(); } // store context state at the end of this slice-segment, in case the next slice is a dependent slice and continues using the CABAC contexts. if( pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag() ) { m_lastSliceSegmentEndContextState.loadContexts( m_pppcRDSbacCoder[0][CI_CURR_BEST] );//ctx end of dep.slice } // stop use of temporary bit counter object. m_pppcRDSbacCoder[0][CI_CURR_BEST]->setBitstream(NULL); m_pcRDGoOnSbacCoder->setBitstream(NULL); // stop use of tempBitCounter. // TODO: optimise cabac_init during compress slice to improve multi-slice operation //if (pcSlice->getPPS()->getCabacInitPresentFlag() && !pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag()) //{ // m_encCABACTableIdx = m_pcEntropyCoder->determineCabacInitIdx(); //} //else //{ // m_encCABACTableIdx = pcSlice->getSliceType(); //} } Void TEncSlice::encodeSlice ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded ) { TComSlice *const pcSlice = pcPic->getSlice(getSliceIdx()); const UInt startCtuTsAddr = pcSlice->getSliceSegmentCurStartCtuTsAddr(); const UInt boundingCtuTsAddr = pcSlice->getSliceSegmentCurEndCtuTsAddr(); const UInt frameWidthInCtus = pcPic->getPicSym()->getFrameWidthInCtus(); const Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag(); const Bool wavefrontsEnabled = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag(); // initialise entropy coder for the slice m_pcSbacCoder->init( (TEncBinIf*)m_pcBinCABAC ); m_pcEntropyCoder->setEntropyCoder ( m_pcSbacCoder ); m_pcEntropyCoder->resetEntropy ( pcSlice ); numBinsCoded = 0; m_pcBinCABAC->setBinCountingEnableFlag( true ); m_pcBinCABAC->setBinsCoded(0); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif DTRACE_CABAC_VL( g_nSymbolCounter++ ); DTRACE_CABAC_T( "\tPOC: " ); DTRACE_CABAC_V( pcPic->getPOC() ); DTRACE_CABAC_T( "\n" ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif if (depSliceSegmentsEnabled) { // modify initial contexts with previous slice segment if this is a dependent slice. const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr ); const UInt currentTileIdx=pcPic->getPicSym()->getTileIdxMap(ctuRsAddr); const TComTile *pCurrentTile=pcPic->getPicSym()->getTComTile(currentTileIdx); const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr(); if( pcSlice->getDependentSliceSegmentFlag() && ctuRsAddr != firstCtuRsAddrOfTile ) { if( pCurrentTile->getTileWidthInCtus() >= 2 || !wavefrontsEnabled ) { m_pcSbacCoder->loadContexts(&m_lastSliceSegmentEndContextState); } } } // for every CTU in the slice segment... for( UInt ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ++ctuTsAddr ) { const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr); const TComTile ¤tTile = *(pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr))); const UInt firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr(); const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus; const UInt tileYPosInCtus = firstCtuRsAddrOfTile / frameWidthInCtus; const UInt ctuXPosInCtus = ctuRsAddr % frameWidthInCtus; const UInt ctuYPosInCtus = ctuRsAddr / frameWidthInCtus; const UInt uiSubStrm=pcPic->getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice); TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr ); m_pcEntropyCoder->setBitstream( &pcSubstreams[uiSubStrm] ); // set up CABAC contexts' state for this CTU if (ctuRsAddr == firstCtuRsAddrOfTile) { if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyCoder->resetEntropy(pcSlice); } } else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled) { // Synchronize cabac probabilities with upper-right CTU if it's available and at the start of a line. if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset { m_pcEntropyCoder->resetEntropy(pcSlice); } TComDataCU *pCtuUp = pCtu->getCtuAbove(); if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus) ) { TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 ); if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) ) { // Top-right is available, so use it. m_pcSbacCoder->loadContexts( &m_entropyCodingSyncContextState ); } } } if ( pcSlice->getSPS()->getUseSAO() ) { Bool bIsSAOSliceEnabled = false; Bool sliceEnabled[MAX_NUM_COMPONENT]; for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++) { ComponentID compId=ComponentID(comp); sliceEnabled[compId] = pcSlice->getSaoEnabledFlag(toChannelType(compId)) && (comp < pcPic->getNumberValidComponents()); if (sliceEnabled[compId]) { bIsSAOSliceEnabled=true; } } if (bIsSAOSliceEnabled) { SAOBlkParam& saoblkParam = (pcPic->getPicSym()->getSAOBlkParam())[ctuRsAddr]; Bool leftMergeAvail = false; Bool aboveMergeAvail= false; //merge left condition Int rx = (ctuRsAddr % frameWidthInCtus); if(rx > 0) { leftMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-1); } //merge up condition Int ry = (ctuRsAddr / frameWidthInCtus); if(ry > 0) { aboveMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-frameWidthInCtus); } m_pcEntropyCoder->encodeSAOBlkParam(saoblkParam, pcPic->getPicSym()->getSPS().getBitDepths(), sliceEnabled, leftMergeAvail, aboveMergeAvail); } } #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceEnable; #endif m_pcCuEncoder->encodeCtu( pCtu ); #if ENC_DEC_TRACE g_bJustDoIt = g_bEncDecTraceDisable; #endif //Store probabilities of second CTU in line into buffer if ( ctuXPosInCtus == tileXPosInCtus+1 && wavefrontsEnabled) { m_entropyCodingSyncContextState.loadContexts( m_pcSbacCoder ); } // terminate the sub-stream, if required (end of slice-segment, end of tile, end of wavefront-CTU-row): if (ctuTsAddr+1 == boundingCtuTsAddr || ( ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus() && ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled) ) ) { m_pcEntropyCoder->encodeTerminatingBit(1); m_pcEntropyCoder->encodeSliceFinish(); // Byte-alignment in slice_data() when new tile pcSubstreams[uiSubStrm].writeByteAlignment(); // write sub-stream size if (ctuTsAddr+1 != boundingCtuTsAddr) { pcSlice->addSubstreamSize( (pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations() ); } } } // CTU-loop if( depSliceSegmentsEnabled ) { m_lastSliceSegmentEndContextState.loadContexts( m_pcSbacCoder );//ctx end of dep.slice } #if ADAPTIVE_QP_SELECTION if( m_pcCfg->getUseAdaptQpSelect() ) { m_pcTrQuant->storeSliceQpNext(pcSlice); // TODO: this will only be storing the adaptive QP state of the very last slice-segment that is not dependent in the frame... Perhaps this should be moved to the compress slice loop. } #endif if (pcSlice->getPPS()->getCabacInitPresentFlag() && !pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag()) { m_encCABACTableIdx = m_pcEntropyCoder->determineCabacInitIdx(pcSlice); } else { m_encCABACTableIdx = pcSlice->getSliceType(); } numBinsCoded = m_pcBinCABAC->getBinsCoded(); } Void TEncSlice::calculateBoundingCtuTsAddrForSlice(UInt &startCtuTSAddrSlice, UInt &boundingCtuTSAddrSlice, Bool &haveReachedTileBoundary, TComPic* pcPic, const Int sliceMode, const Int sliceArgument) { TComSlice* pcSlice = pcPic->getSlice(getSliceIdx()); const UInt numberOfCtusInFrame = pcPic->getNumberOfCtusInFrame(); const TComPPS &pps=*(pcSlice->getPPS()); boundingCtuTSAddrSlice=0; haveReachedTileBoundary=false; switch (sliceMode) { case FIXED_NUMBER_OF_CTU: { UInt ctuAddrIncrement = sliceArgument; boundingCtuTSAddrSlice = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame; } break; case FIXED_NUMBER_OF_BYTES: boundingCtuTSAddrSlice = numberOfCtusInFrame; // This will be adjusted later if required. break; case FIXED_NUMBER_OF_TILES: { const UInt tileIdx = pcPic->getPicSym()->getTileIdxMap( pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTSAddrSlice) ); const UInt tileTotalCount = (pcPic->getPicSym()->getNumTileColumnsMinus1()+1) * (pcPic->getPicSym()->getNumTileRowsMinus1()+1); UInt ctuAddrIncrement = 0; for(UInt tileIdxIncrement = 0; tileIdxIncrement < sliceArgument; tileIdxIncrement++) { if((tileIdx + tileIdxIncrement) < tileTotalCount) { UInt tileWidthInCtus = pcPic->getPicSym()->getTComTile(tileIdx + tileIdxIncrement)->getTileWidthInCtus(); UInt tileHeightInCtus = pcPic->getPicSym()->getTComTile(tileIdx + tileIdxIncrement)->getTileHeightInCtus(); ctuAddrIncrement += (tileWidthInCtus * tileHeightInCtus); } } boundingCtuTSAddrSlice = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame; } break; default: boundingCtuTSAddrSlice = numberOfCtusInFrame; break; } // Adjust for tiles and wavefronts. const Bool wavefrontsAreEnabled = pps.getEntropyCodingSyncEnabledFlag(); if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) && (pps.getNumTileRowsMinus1() > 0 || pps.getNumTileColumnsMinus1() > 0)) { const UInt ctuRSAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTSAddrSlice); const UInt startTileIdx = pcPic->getPicSym()->getTileIdxMap(ctuRSAddr); const TComTile *pStartingTile = pcPic->getPicSym()->getTComTile(startTileIdx); const UInt tileStartTsAddr = pcPic->getPicSym()->getCtuRsToTsAddrMap(pStartingTile->getFirstCtuRsAddr()); const UInt tileStartWidth = pStartingTile->getTileWidthInCtus(); const UInt tileStartHeight = pStartingTile->getTileHeightInCtus(); const UInt tileLastTsAddr_excl = tileStartTsAddr + tileStartWidth*tileStartHeight; const UInt tileBoundingCtuTsAddrSlice = tileLastTsAddr_excl; const UInt ctuColumnOfStartingTile = ((startCtuTSAddrSlice-tileStartTsAddr)%tileStartWidth); if (wavefrontsAreEnabled && ctuColumnOfStartingTile!=0) { // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row const UInt numberOfCTUsToEndOfRow = tileStartWidth - ctuColumnOfStartingTile; const UInt wavefrontTileBoundingCtuAddrSlice = startCtuTSAddrSlice + numberOfCTUsToEndOfRow; if (wavefrontTileBoundingCtuAddrSlice < boundingCtuTSAddrSlice) { boundingCtuTSAddrSlice = wavefrontTileBoundingCtuAddrSlice; } } if (tileBoundingCtuTsAddrSlice < boundingCtuTSAddrSlice) { boundingCtuTSAddrSlice = tileBoundingCtuTsAddrSlice; haveReachedTileBoundary = true; } } else if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) && wavefrontsAreEnabled && ((startCtuTSAddrSlice % pcPic->getFrameWidthInCtus()) != 0)) { // Adjust for wavefronts (no tiles). // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row boundingCtuTSAddrSlice = min(boundingCtuTSAddrSlice, startCtuTSAddrSlice - (startCtuTSAddrSlice % pcPic->getFrameWidthInCtus()) + (pcPic->getFrameWidthInCtus())); } } /** Determines the starting and bounding CTU address of current slice / dependent slice * \param [out] startCtuTsAddr * \param [out] boundingCtuTsAddr * \param [in] pcPic * Updates startCtuTsAddr, boundingCtuTsAddr with appropriate CTU address */ Void TEncSlice::xDetermineStartAndBoundingCtuTsAddr ( UInt& startCtuTsAddr, UInt& boundingCtuTsAddr, TComPic* pcPic ) { TComSlice* pcSlice = pcPic->getSlice(getSliceIdx()); // Non-dependent slice UInt startCtuTsAddrSlice = pcSlice->getSliceCurStartCtuTsAddr(); Bool haveReachedTileBoundarySlice = false; UInt boundingCtuTsAddrSlice; calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSlice, boundingCtuTsAddrSlice, haveReachedTileBoundarySlice, pcPic, m_pcCfg->getSliceMode(), m_pcCfg->getSliceArgument()); pcSlice->setSliceCurEndCtuTsAddr( boundingCtuTsAddrSlice ); pcSlice->setSliceCurStartCtuTsAddr( startCtuTsAddrSlice ); // Dependent slice UInt startCtuTsAddrSliceSegment = pcSlice->getSliceSegmentCurStartCtuTsAddr(); Bool haveReachedTileBoundarySliceSegment = false; UInt boundingCtuTsAddrSliceSegment; calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSliceSegment, boundingCtuTsAddrSliceSegment, haveReachedTileBoundarySliceSegment, pcPic, m_pcCfg->getSliceSegmentMode(), m_pcCfg->getSliceSegmentArgument()); if (boundingCtuTsAddrSliceSegment>boundingCtuTsAddrSlice) { boundingCtuTsAddrSliceSegment = boundingCtuTsAddrSlice; } pcSlice->setSliceSegmentCurEndCtuTsAddr( boundingCtuTsAddrSliceSegment ); pcSlice->setSliceSegmentCurStartCtuTsAddr(startCtuTsAddrSliceSegment); // Make a joint decision based on reconstruction and dependent slice bounds startCtuTsAddr = max(startCtuTsAddrSlice , startCtuTsAddrSliceSegment ); boundingCtuTsAddr = boundingCtuTsAddrSliceSegment; } Double TEncSlice::xGetQPValueAccordingToLambda ( Double lambda ) { return 4.2005*log(lambda) + 13.7122; } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncSlice.h000066400000000000000000000166321442026013100203730ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncSlice.h \brief slice encoder class (header) */ #ifndef __TENCSLICE__ #define __TENCSLICE__ // Include files #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComList.h" #include "TLibCommon/TComPic.h" #include "TLibCommon/TComPicYuv.h" #include "TEncCu.h" #include "WeightPredAnalysis.h" #include "TEncRateCtrl.h" //! \ingroup TLibEncoder //! \{ class TEncTop; class TEncGOP; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// slice encoder class class TEncSlice : public WeightPredAnalysis { private: // encoder configuration TEncCfg* m_pcCfg; ///< encoder configuration class // pictures TComList* m_pcListPic; ///< list of pictures TComPicYuv m_picYuvPred; ///< prediction picture buffer TComPicYuv m_picYuvResi; ///< residual picture buffer // processing units TEncGOP* m_pcGOPEncoder; ///< GOP encoder TEncCu* m_pcCuEncoder; ///< CU encoder // encoder search TEncSearch* m_pcPredSearch; ///< encoder search class // coding tools TEncEntropy* m_pcEntropyCoder; ///< entropy encoder TEncSbac* m_pcSbacCoder; ///< SBAC encoder TEncBinCABAC* m_pcBinCABAC; ///< Bin encoder CABAC TComTrQuant* m_pcTrQuant; ///< transform & quantization // RD optimization TComRdCost* m_pcRdCost; ///< RD cost computation TEncSbac*** m_pppcRDSbacCoder; ///< storage for SBAC-based RD optimization TEncSbac* m_pcRDGoOnSbacCoder; ///< go-on SBAC encoder UInt64 m_uiPicTotalBits; ///< total bits for the picture UInt64 m_uiPicDist; ///< total distortion for the picture Double m_dPicRdCost; ///< picture-level RD cost std::vector m_vdRdPicLambda; ///< array of lambda candidates std::vector m_vdRdPicQp; ///< array of picture QP candidates (double-type for lambda) std::vector m_viRdPicQp; ///< array of picture QP candidates (Int-type) TEncRateCtrl* m_pcRateCtrl; ///< Rate control manager UInt m_uiSliceIdx; TEncSbac m_lastSliceSegmentEndContextState; ///< context storage for state at the end of the previous slice-segment (used for dependent slices only). TEncSbac m_entropyCodingSyncContextState; ///< context storate for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row SliceType m_encCABACTableIdx; Int m_gopID; Double calculateLambda( const TComSlice* pSlice, const Int GOPid, const Int depth, const Double refQP, const Double dQP, Int &iQP ); Void setUpLambda(TComSlice* slice, const Double dLambda, Int iQP); Void calculateBoundingCtuTsAddrForSlice(UInt &startCtuTSAddrSlice, UInt &boundingCtuTSAddrSlice, Bool &haveReachedTileBoundary, TComPic* pcPic, const Int sliceMode, const Int sliceArgument); public: TEncSlice(); virtual ~TEncSlice(); Void create ( Int iWidth, Int iHeight, ChromaFormat chromaFormat, UInt iMaxCUWidth, UInt iMaxCUHeight, UChar uhTotalDepth ); Void destroy (); Void init ( TEncTop* pcEncTop ); Void resetEncoderDecisions() { m_encCABACTableIdx = I_SLICE; } /// preparation of slice encoding (reference marking, QP and lambda) Void initEncSlice ( TComPic* pcPic, const Int pocLast, const Int pocCurr, const Int iGOPid, TComSlice*& rpcSlice, const Bool isField ); Void resetQP ( TComPic* pic, Int sliceQP, Double lambda ); Void setGopID( Int iGopID ) { m_gopID = iGopID; } Int getGopID() const { return m_gopID; } Void updateLambda(TComSlice* pSlice, Double dQP); // compress and encode slice Void precompressSlice ( TComPic* pcPic ); ///< precompress slice for multi-loop slice-level QP opt. Void compressSlice ( TComPic* pcPic, const Bool bCompressEntireSlice, const Bool bFastDeltaQP ); ///< analysis stage of slice Void calCostSliceI ( TComPic* pcPic ); Void encodeSlice ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded ); // misc. functions Void setSearchRange ( TComSlice* pcSlice ); ///< set ME range adaptively TEncCu* getCUEncoder() { return m_pcCuEncoder; } ///< CU encoder Void xDetermineStartAndBoundingCtuTsAddr ( UInt& startCtuTsAddr, UInt& boundingCtuTsAddr, TComPic* pcPic ); UInt getSliceIdx() { return m_uiSliceIdx; } Void setSliceIdx(UInt i) { m_uiSliceIdx = i; } SliceType getEncCABACTableIdx() const { return m_encCABACTableIdx; } private: Double xGetQPValueAccordingToLambda ( Double lambda ); }; //! \} #endif // __TENCSLICE__ HM-HM-18.0/source/Lib/TLibEncoder/TEncTemporalFilter.cpp000066400000000000000000000772231442026013100226230ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncTemporalFilter.cpp \brief TEncTemporalFilter class */ #include "TEncTemporalFilter.h" #include // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== const Double TEncTemporalFilter::s_chromaFactor = 0.55; const Double TEncTemporalFilter::s_sigmaMultiplier = 9.0; const Double TEncTemporalFilter::s_sigmaZeroPoint = 10.0; const Int TEncTemporalFilter::s_motionVectorFactor = 16; const Int TEncTemporalFilter::s_padding = 128; const Int TEncTemporalFilter::s_interpolationFilter[16][8] = { { 0, 0, 0, 64, 0, 0, 0, 0 }, //0 { 0, 1, -3, 64, 4, -2, 0, 0 }, //1 -->--> { 0, 1, -6, 62, 9, -3, 1, 0 }, //2 --> { 0, 2, -8, 60, 14, -5, 1, 0 }, //3 -->--> { 0, 2, -9, 57, 19, -7, 2, 0 }, //4 { 0, 3, -10, 53, 24, -8, 2, 0 }, //5 -->--> { 0, 3, -11, 50, 29, -9, 2, 0 }, //6 --> { 0, 3, -11, 44, 35, -10, 3, 0 }, //7 -->--> { 0, 1, -7, 38, 38, -7, 1, 0 }, //8 { 0, 3, -10, 35, 44, -11, 3, 0 }, //9 -->--> { 0, 2, -9, 29, 50, -11, 3, 0 }, //10--> { 0, 2, -8, 24, 53, -10, 3, 0 }, //11-->--> { 0, 2, -7, 19, 57, -9, 2, 0 }, //12 { 0, 1, -5, 14, 60, -8, 2, 0 }, //13-->--> { 0, 1, -3, 9, 62, -6, 1, 0 }, //14--> { 0, 0, -2, 4, 64, -3, 1, 0 } //15-->--> }; #if JVET_V0056_MCTF const Double TEncTemporalFilter::s_refStrengths[2][4] = { // abs(POC offset) // 1, 2 3 4 {0.85, 0.57, 0.41, 0.33}, // w future refs {1.13, 0.97, 0.81, 0.57}, // w/o future refs }; #else const Double TEncTemporalFilter::s_refStrengths[2][2] = { // abs(POC offset) // 1, 2 {0.85, 0.60}, // w future refs {1.20, 1.00}, // w/o future refs }; #endif #if JVET_Y0077_BIM const Int TEncTemporalFilter::s_cuTreeThresh[4] = { 75, 60, 30, 15 }; #endif TEncTemporalFilter::TEncTemporalFilter() : m_FrameSkip(0), m_chromaFormatIDC(NUM_CHROMA_FORMAT), m_sourceWidth(0), m_sourceHeight(0), m_QP(0), m_GOPSize(0), m_framesToBeEncoded(0), m_bClipInputVideoToRec709Range(false), m_inputColourSpaceConvert(NUMBER_INPUT_COLOUR_SPACE_CONVERSIONS) {} void TEncTemporalFilter::init(const Int frameSkip, const Int inputBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int internalBitDepth[MAX_NUM_CHANNEL_TYPE], const Int width, const Int height, const Int *padding, const Int frames, const Bool Rec709, const std::string &filename, const ChromaFormat inputChromaFormatIDC, const InputColourSpaceConversion colorSpaceConv, const Int QP, const Int GOPSize, const std::map &temporalFilterStrengths, const Int pastRefs, const Int futureRefs, const Int firstValidFrame, #if !JVET_Y0077_BIM const Int lastValidFrame) #else const Int lastValidFrame, const Bool mctfEnabled, std::map *adaptQPmap, const Bool bimEnabled) #endif { m_FrameSkip = frameSkip; for (Int i = 0; i < MAX_NUM_CHANNEL_TYPE; i++) { m_inputBitDepth[i] = inputBitDepth[i]; m_MSBExtendedBitDepth[i] = MSBExtendedBitDepth[i]; m_internalBitDepth[i] = internalBitDepth[i]; } m_sourceWidth = width; m_sourceHeight = height; for (Int i = 0; i < 2; i++) { m_sourcePadding[i] = padding[i]; } m_framesToBeEncoded = frames; // NOT USED. m_bClipInputVideoToRec709Range = Rec709; m_inputFileName = filename; m_chromaFormatIDC = inputChromaFormatIDC; m_inputColourSpaceConvert = colorSpaceConv; m_QP = QP; m_GOPSize = GOPSize; // NOT USED. m_temporalFilterStrengths = temporalFilterStrengths; m_pastRefs = pastRefs; m_futureRefs = futureRefs; m_firstValidFrame = firstValidFrame; m_lastValidFrame = lastValidFrame; #if JVET_Y0077_BIM m_mctfEnabled = mctfEnabled; m_bimEnabled = bimEnabled; m_numCTU = ((width + 63) / 64) * ((height + 63) / 64); m_ctuAdaptQP = adaptQPmap; #endif } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Bool TEncTemporalFilter::filter(TComPicYuv *orgPic, Int receivedPoc) { Bool isFilterThisFrame = false; if (m_QP >= 17) // disable filter for QP < 17 { for (map::iterator it = m_temporalFilterStrengths.begin(); it != m_temporalFilterStrengths.end(); ++it) { Int filteredFrame = it->first; if (receivedPoc % filteredFrame == 0) { isFilterThisFrame = true; break; } } } if (isFilterThisFrame) { const Int currentFilePoc = receivedPoc + m_FrameSkip; const Int firstFrame = std::max(currentFilePoc - m_pastRefs, m_firstValidFrame); const Int lastFrame = std::min(currentFilePoc + m_futureRefs, m_lastValidFrame); TVideoIOYuv yuvFrames; yuvFrames.open(m_inputFileName, false, m_inputBitDepth, m_MSBExtendedBitDepth, m_internalBitDepth); yuvFrames.skipFrames(firstFrame, m_sourceWidth - m_sourcePadding[0], m_sourceHeight - m_sourcePadding[1], m_chromaFormatIDC); std::deque srcFrameInfo; // subsample original picture so it only needs to be done once TComPicYuv origPadded; origPadded.createWithoutCUInfo(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, true, s_padding, s_padding); orgPic->copyToPic(&origPadded); origPadded.extendPicBorder(); TComPicYuv origSubsampled2; TComPicYuv origSubsampled4; subsampleLuma(origPadded, origSubsampled2); subsampleLuma(origSubsampled2, origSubsampled4); // determine motion vectors for (Int poc = firstFrame; poc <= lastFrame; poc++) { if (poc == currentFilePoc) { // hop over frame that will be filtered yuvFrames.skipFrames(1, m_sourceWidth - m_sourcePadding[0], m_sourceHeight - m_sourcePadding[1], m_chromaFormatIDC); continue; } srcFrameInfo.push_back(TemporalFilterSourcePicInfo()); TemporalFilterSourcePicInfo &srcPic=srcFrameInfo.back(); TComPicYuv dummyPicBufferTO; // Only used temporary in yuvFrames.read srcPic.picBuffer.createWithoutCUInfo(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, true, s_padding, s_padding); dummyPicBufferTO.createWithoutCUInfo(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, true, s_padding, s_padding); if (!yuvFrames.read(&srcPic.picBuffer, &dummyPicBufferTO, m_inputColourSpaceConvert, m_sourcePadding, m_chromaFormatIDC, m_bClipInputVideoToRec709Range)) { // eof or read fail srcPic.picBuffer.destroy(); srcFrameInfo.pop_back(); break; } srcPic.picBuffer.extendPicBorder(); srcPic.mvs.allocate(m_sourceWidth / 4, m_sourceHeight / 4); motionEstimation(srcPic.mvs, origPadded, srcPic.picBuffer, origSubsampled2, origSubsampled4); srcPic.origOffset = poc - currentFilePoc; } // filter TComPicYuv newOrgPic; newOrgPic.createWithoutCUInfo(m_sourceWidth, m_sourceHeight, m_chromaFormatIDC, true, s_padding, s_padding); Double overallStrength = -1.0; for (map::iterator it = m_temporalFilterStrengths.begin(); it != m_temporalFilterStrengths.end(); ++it) { Int frame = it->first; Double strength = it->second; if (receivedPoc % frame == 0) { overallStrength = strength; } } #if JVET_Y0077_BIM const int numRefs = Int(srcFrameInfo.size()); if ( m_bimEnabled && ( numRefs > 0 ) ) { const Int bimFirstFrame = std::max(currentFilePoc - 2, firstFrame); const Int bimLastFrame = std::min(currentFilePoc + 2, lastFrame); std::vector sumError(m_numCTU * 2, 0); std::vector blkCount(m_numCTU * 2, 0); int frameIndex = bimFirstFrame - firstFrame; Int distFactor[2] = {3,3}; Int* qpMap = new Int[m_numCTU]; for (int poc = bimFirstFrame; poc <= bimLastFrame; poc++) { if ((poc < 0) || (poc == currentFilePoc) || (frameIndex >= numRefs)) { continue; } Int dist = abs(poc - currentFilePoc) - 1; distFactor[dist]--; TemporalFilterSourcePicInfo &srcPic = srcFrameInfo.at(frameIndex); for (Int y = 0; y < srcPic.mvs.h() / 2; y++) // going over in 8x8 block steps { for (Int x = 0; x < srcPic.mvs.w() / 2; x++) { Int blocksPerRow = (srcPic.mvs.w() / 2 + 7) / 8; Int ctuX = x / 8; Int ctuY = y / 8; Int ctuId = ctuY * blocksPerRow + ctuX; sumError[dist * m_numCTU + ctuId] += srcPic.mvs.get(x, y).error; blkCount[dist * m_numCTU + ctuId] += 1; } } frameIndex++; } Double weight = (receivedPoc % 16) ? 0.6 : 1; const Double center = 45.0; for (Int i = 0; i < m_numCTU; i++) { Int avgErrD1 = (Int)((sumError[i] / blkCount[i]) * distFactor[0]); Int avgErrD2 = (Int)((sumError[i + m_numCTU] / blkCount[i + m_numCTU]) * distFactor[1]); Int weightedErr = std::max(avgErrD1, avgErrD2) + abs(avgErrD2 - avgErrD1) * 3; weightedErr = (Int)(weightedErr * weight + (1 - weight) * center); if (weightedErr > s_cuTreeThresh[0]) { qpMap[i] = 2; } else if (weightedErr > s_cuTreeThresh[1]) { qpMap[i] = 1; } else if (weightedErr < s_cuTreeThresh[3]) { qpMap[i] = -2; } else if (weightedErr < s_cuTreeThresh[2]) { qpMap[i] = -1; } else { qpMap[i] = 0; } } m_ctuAdaptQP->insert({ receivedPoc, qpMap }); } if ( m_mctfEnabled && ( numRefs > 0 ) ) { #endif bilateralFilter(origPadded, srcFrameInfo, newOrgPic, overallStrength); // move filtered to orgPic newOrgPic.copyToPic(orgPic); #if JVET_Y0077_BIM } #endif yuvFrames.close(); return true; } return false; } // ==================================================================================================================== // Private member functions // ==================================================================================================================== Void TEncTemporalFilter::subsampleLuma(const TComPicYuv &input, TComPicYuv &output, const Int factor) const { const Int newWidth = input.getWidth(COMPONENT_Y) / factor; const Int newHeight = input.getHeight(COMPONENT_Y) / factor; output.createWithoutCUInfo(newWidth, newHeight, input.getChromaFormat(), true, s_padding, s_padding); const Pel* srcRow =input.getAddr(COMPONENT_Y); const UInt srcStride=input.getStride(COMPONENT_Y); Pel *dstRow =output.getAddr(COMPONENT_Y); const UInt dstStride=output.getStride(COMPONENT_Y); for (Int y = 0; y < newHeight; y++, srcRow+=factor*srcStride, dstRow+=dstStride) { const Pel *inRow = srcRow; const Pel *inRowBelow = srcRow+srcStride; Pel *target = dstRow; for (Int x = 0; x < newWidth; x++) { target[x] = (inRow[0] + inRowBelow[0] + inRow[1] + inRowBelow[1] + 2) >> 2; inRow += 2; inRowBelow += 2; } } output.extendPicBorder(); } Int TEncTemporalFilter::motionErrorLuma(const TComPicYuv &orig, const TComPicYuv &buffer, const Int x, const Int y, Int dx, Int dy, const Int bs, const Int besterror /* = 8 * 8 * 1024 * 1024*/) const { const Pel* origOrigin = orig.getAddr(COMPONENT_Y); const Int origStride = orig.getStride(COMPONENT_Y); const Pel *buffOrigin = buffer.getAddr(COMPONENT_Y); const Int buffStride = buffer.getStride(COMPONENT_Y); Int error = 0;// dx * 10 + dy * 10; if (((dx | dy) & 0xF) == 0) { dx /= s_motionVectorFactor; dy /= s_motionVectorFactor; for (Int y1 = 0; y1 < bs; y1++) { const Pel* origRowStart = origOrigin + (y+y1)*origStride + x; const Pel* bufferRowStart = buffOrigin + (y+y1+dy)*buffStride + (x+dx); for (Int x1 = 0; x1 < bs; x1 += 2) { Int diff = origRowStart[x1] - bufferRowStart[x1]; error += diff * diff; diff = origRowStart[x1 + 1] - bufferRowStart[x1 + 1]; error += diff * diff; } if (error > besterror) { return error; } } } else { const Int *xFilter = s_interpolationFilter[dx & 0xF]; const Int *yFilter = s_interpolationFilter[dy & 0xF]; Int tempArray[64 + 8][64]; Int iSum, iBase; for (Int y1 = 1; y1 < bs + 7; y1++) { const Int yOffset = y + y1 + (dy >> 4) - 3; const Pel *sourceRow = buffOrigin + (yOffset)*buffStride + 0; for (Int x1 = 0; x1 < bs; x1++) { iSum = 0; iBase = x + x1 + (dx >> 4) - 3; const Pel *rowStart = sourceRow + iBase; iSum += xFilter[1] * rowStart[1]; iSum += xFilter[2] * rowStart[2]; iSum += xFilter[3] * rowStart[3]; iSum += xFilter[4] * rowStart[4]; iSum += xFilter[5] * rowStart[5]; iSum += xFilter[6] * rowStart[6]; tempArray[y1][x1] = iSum; } } const Pel maxSampleValue = (1<> 12; iSum = iSum < 0 ? 0 : (iSum > maxSampleValue ? maxSampleValue : iSum); error += (iSum - origRow[x + x1]) * (iSum - origRow[x + x1]); } if (error > besterror) { return error; } } } return error; } Void TEncTemporalFilter::motionEstimationLuma(Array2D &mvs, const TComPicYuv &orig, const TComPicYuv &buffer, const Int blockSize, const Array2D *previous, const Int factor, const Bool doubleRes) const { #if JVET_V0056_MCTF || JVET_Y0077_BIM Int range = doubleRes ? 0 : 5; #else Int range = 5; #endif const Int stepSize = blockSize; const Int origWidth = orig.getWidth(COMPONENT_Y); const Int origHeight = orig.getHeight(COMPONENT_Y); #if JVET_V0056_MCTF || JVET_Y0077_BIM for (Int blockY = 0; blockY + blockSize <= origHeight; blockY += stepSize) { for (Int blockX = 0; blockX + blockSize <= origWidth; blockX += stepSize) #else for (Int blockY = 0; blockY + blockSize < origHeight; blockY += stepSize) { for (Int blockX = 0; blockX + blockSize < origWidth; blockX += stepSize) #endif { MotionVector best; if (previous == NULL) { range = 8; } else { #if JVET_V0056_MCTF || JVET_Y0077_BIM for (Int py = -1; py <= 1; py++) #else for (Int py = -2; py <= 2; py++) #endif { Int testy = blockY / (2 * blockSize) + py; #if JVET_V0056_MCTF || JVET_Y0077_BIM for (Int px = -1; px <= 1; px++) #else for (Int px = -2; px <= 2; px++) #endif { Int testx = blockX / (2 * blockSize) + px; if ((testx >= 0) && (testx < origWidth / (2 * blockSize)) && (testy >= 0) && (testy < origHeight / (2 * blockSize))) { MotionVector old = previous->get(testx, testy); Int error = motionErrorLuma(orig, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, best.error); if (error < best.error) { best.set(old.x * factor, old.y * factor, error); } } } } #if JVET_V0056_MCTF || JVET_Y0077_BIM Int error = motionErrorLuma(orig, buffer, blockX, blockY, 0, 0, blockSize, best.error); if (error < best.error) { best.set(0, 0, error); } #endif } MotionVector prevBest = best; for (Int y2 = prevBest.y / s_motionVectorFactor - range; y2 <= prevBest.y / s_motionVectorFactor + range; y2++) { for (Int x2 = prevBest.x / s_motionVectorFactor - range; x2 <= prevBest.x / s_motionVectorFactor + range; x2++) { Int error = motionErrorLuma(orig, buffer, blockX, blockY, x2 * s_motionVectorFactor, y2 * s_motionVectorFactor, blockSize, best.error); if (error < best.error) { best.set(x2 * s_motionVectorFactor, y2 * s_motionVectorFactor, error); } } } if (doubleRes) { // merge into one loop, probably with precision array (here [12, 3] or maybe [4, 1]) with setable number of iterations prevBest = best; Int doubleRange = 3 * 4; for (Int y2 = prevBest.y - doubleRange; y2 <= prevBest.y + doubleRange; y2 += 4) { for (Int x2 = prevBest.x - doubleRange; x2 <= prevBest.x + doubleRange; x2 += 4) { Int error = motionErrorLuma(orig, buffer, blockX, blockY, x2, y2, blockSize, best.error); if (error < best.error) { best.set(x2, y2, error); } } } prevBest = best; doubleRange = 3; for (Int y2 = prevBest.y - doubleRange; y2 <= prevBest.y + doubleRange; y2++) { for (Int x2 = prevBest.x - doubleRange; x2 <= prevBest.x + doubleRange; x2++) { Int error = motionErrorLuma(orig, buffer, blockX, blockY, x2, y2, blockSize, best.error); if (error < best.error) { best.set(x2, y2, error); } } } } #if JVET_V0056_MCTF || JVET_Y0077_BIM if (blockY > 0) { MotionVector aboveMV = mvs.get(blockX / stepSize, (blockY - stepSize) / stepSize); int error = motionErrorLuma(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, best.error); if (error < best.error) { best.set(aboveMV.x, aboveMV.y, error); } } if (blockX > 0) { MotionVector leftMV = mvs.get((blockX - stepSize) / stepSize, blockY / stepSize); int error = motionErrorLuma(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, best.error); if (error < best.error) { best.set(leftMV.x, leftMV.y, error); } } // calculate average double avg = 0.0; for (int x1 = 0; x1 < blockSize; x1++) { for (int y1 = 0; y1 < blockSize; y1++) { avg = avg + *(orig.getAddr(COMPONENT_Y) + (blockX + x1 + orig.getStride(COMPONENT_Y) * (blockY + y1))); } } avg = avg / (blockSize * blockSize); // calculate variance double variance = 0; for (int x1 = 0; x1 < blockSize; x1++) { for (int y1 = 0; y1 < blockSize; y1++) { int pix = *(orig.getAddr(COMPONENT_Y) + (blockX + x1 + orig.getStride(COMPONENT_Y) * (blockY + y1))); variance = variance + (pix - avg) * (pix - avg); } } best.error = (Int) (20 * ((best.error + 5.0) / (variance + 5.0)) + (best.error / (blockSize * blockSize)) / 50); #endif mvs.get(blockX / stepSize, blockY / stepSize) = best; } } } Void TEncTemporalFilter::motionEstimation(Array2D &mv, const TComPicYuv &orgPic, const TComPicYuv &buffer, const TComPicYuv &origSubsampled2, const TComPicYuv &origSubsampled4) const { const Int width = m_sourceWidth; const Int height = m_sourceHeight; Array2D mv_0(width / 16, height / 16); Array2D mv_1(width / 16, height / 16); Array2D mv_2(width / 16, height / 16); TComPicYuv bufferSub2; TComPicYuv bufferSub4; subsampleLuma(buffer, bufferSub2); subsampleLuma(bufferSub2, bufferSub4); motionEstimationLuma(mv_0, origSubsampled4, bufferSub4, 16); motionEstimationLuma(mv_1, origSubsampled2, bufferSub2, 16, &mv_0, 2); motionEstimationLuma(mv_2, orgPic, buffer, 16, &mv_1, 2); motionEstimationLuma(mv, orgPic, buffer, 8, &mv_2, 1, true); } Void TEncTemporalFilter::applyMotion(const Array2D &mvs, const TComPicYuv &input, TComPicYuv &output) const { static const Int lumaBlockSize=8; for(Int c=0; c< getNumberValidComponents(m_chromaFormatIDC); c++) { const ComponentID compID=(ComponentID)c; const Int csx=getComponentScaleX(compID, m_chromaFormatIDC); const Int csy=getComponentScaleY(compID, m_chromaFormatIDC); const Int blockSizeX = lumaBlockSize>>csx; const Int blockSizeY = lumaBlockSize>>csy; const Int height = input.getHeight(compID); const Int width = input.getWidth(compID); const Pel maxValue = (1<> csx ; const Int dy = mv.y >> csy ; const Int xInt = mv.x >> (4+csx) ; const Int yInt = mv.y >> (4+csy) ; const Int *xFilter = s_interpolationFilter[dx & 0xf]; const Int *yFilter = s_interpolationFilter[dy & 0xf]; // will add 6 bit. const Int numFilterTaps=7; const Int centreTapOffset=3; Int tempArray[lumaBlockSize + numFilterTaps][lumaBlockSize]; for (Int by = 1; by < blockSizeY + numFilterTaps; by++) { const Int yOffset = y + by + yInt - centreTapOffset; const Pel *sourceRow = pSrcImage+yOffset*srcStride; for (Int bx = 0; bx < blockSizeX; bx++) { Int iBase = x + bx + xInt - centreTapOffset; const Pel *rowStart = sourceRow + iBase; Int iSum = 0; iSum += xFilter[1] * rowStart[1]; iSum += xFilter[2] * rowStart[2]; iSum += xFilter[3] * rowStart[3]; iSum += xFilter[4] * rowStart[4]; iSum += xFilter[5] * rowStart[5]; iSum += xFilter[6] * rowStart[6]; tempArray[by][bx] = iSum; } } Pel *pDstRow=pDstImage+y*dstStride; for (Int by = 0; by < blockSizeY; by++, pDstRow+=dstStride) { Pel *pDstPel=pDstRow+x; for (Int bx = 0; bx < blockSizeX; bx++, pDstPel++) { Int iSum = 0; iSum += yFilter[1] * tempArray[by + 1][bx]; iSum += yFilter[2] * tempArray[by + 2][bx]; iSum += yFilter[3] * tempArray[by + 3][bx]; iSum += yFilter[4] * tempArray[by + 4][bx]; iSum += yFilter[5] * tempArray[by + 5][bx]; iSum += yFilter[6] * tempArray[by + 6][bx]; iSum = (iSum + (1 << 11)) >> 12; iSum = iSum < 0 ? 0 : (iSum > maxValue ? maxValue : iSum); *pDstPel = iSum; } } } } } } Void TEncTemporalFilter::bilateralFilter(const TComPicYuv &orgPic, #if JVET_V0056_MCTF || JVET_Y0077_BIM std::deque &srcFrameInfo, #else const std::deque &srcFrameInfo, #endif TComPicYuv &newOrgPic, Double overallStrength) const { const int numRefs = Int(srcFrameInfo.size()); std::vector correctedPics(numRefs); for (Int i = 0; i < numRefs; i++) { correctedPics[i].createWithoutCUInfo( m_sourceWidth, m_sourceHeight, orgPic.getChromaFormat(), true, s_padding, s_padding ); applyMotion(srcFrameInfo[i].mvs, srcFrameInfo[i].picBuffer, correctedPics[i]); } const Int refStrengthRow = m_futureRefs > 0 ? 0 : 1; const Double lumaSigmaSq = (m_QP - s_sigmaZeroPoint) * (m_QP - s_sigmaZeroPoint) * s_sigmaMultiplier; const Double chromaSigmaSq = 30 * 30; for(Int c=0; c< getNumberValidComponents(m_chromaFormatIDC); c++) { const ComponentID compID=(ComponentID)c; const Int height = orgPic.getHeight(compID); const Int width = orgPic.getWidth(compID); const Pel *srcPelRow = orgPic.getAddr(compID); const Int srcStride = orgPic.getStride(compID); Pel *dstPelRow = newOrgPic.getAddr(compID); const Int dstStride = newOrgPic.getStride(compID); const Double sigmaSq = isChroma(compID)? chromaSigmaSq : lumaSigmaSq; const Double weightScaling = overallStrength * (isChroma(compID) ? s_chromaFactor : 0.4); const Pel maxSampleValue = (1<>csx; const Int blkSizeY = lumaBlockSize>>csy; #endif for (Int y = 0; y < height; y++, srcPelRow+=srcStride, dstPelRow+=dstStride) { const Pel *srcPel=srcPelRow; Pel *dstPel=dstPelRow; for (Int x = 0; x < width; x++, srcPel++, dstPel++) { const Int orgVal = (Int) *srcPel; Double temporalWeightSum = 1.0; Double newVal = (Double) orgVal; #if JVET_V0056_MCTF || JVET_Y0077_BIM if ((y % blkSizeY == 0) && (x % blkSizeX == 0)) { for (Int i = 0; i < numRefs; i++) { Double variance = 0, diffsum = 0; const ptrdiff_t refStride = correctedPics[i].getStride(compID); const Pel *refPel = correctedPics[i].getAddr(compID) + y * refStride + x; for (Int y1 = 0; y1 < blkSizeY; y1++) { for (Int x1 = 0; x1 < blkSizeX; x1++) { const Pel pix = *(srcPel + srcStride * y1 + x1); const Pel ref = *(refPel + refStride * y1 + x1); const Int diff = pix - ref; variance += diff * diff; if (x1 != blkSizeX - 1) { const Pel pixR = *(srcPel + srcStride * y1 + x1 + 1); const Pel refR = *(refPel + refStride * y1 + x1 + 1); const Int diffR = pixR - refR; diffsum += (diffR - diff) * (diffR - diff); } if (y1 != blkSizeY - 1) { const Pel pixD = *(srcPel + srcStride * y1 + x1 + srcStride); const Pel refD = *(refPel + refStride * y1 + x1 + refStride); const Int diffD = pixD - refD; diffsum += (diffD - diff) * (diffD - diff); } } } const int cntV = blkSizeX * blkSizeY; const int cntD = 2 * cntV - blkSizeX - blkSizeY; srcFrameInfo[i].mvs.get(x / blkSizeX, y / blkSizeY).noise = (int) round((15.0 * cntD / cntV * variance + 5.0) / (diffsum + 5.0)); } } Double minError = 9999999; for (Int i = 0; i < numRefs; i++) { minError = std::min(minError, (Double) srcFrameInfo[i].mvs.get(x / blkSizeX, y / blkSizeY).error); } #endif for (Int i = 0; i < numRefs; i++) { #if JVET_V0056_MCTF || JVET_Y0077_BIM const Int error = srcFrameInfo[i].mvs.get(x / blkSizeX, y / blkSizeY).error; const Int noise = srcFrameInfo[i].mvs.get(x / blkSizeX, y / blkSizeY).noise; #endif const Pel *pCorrectedPelPtr=correctedPics[i].getAddr(compID)+(y*correctedPics[i].getStride(compID)+x); const Int refVal = (Int) *pCorrectedPelPtr; Double diff = (Double)(refVal - orgVal); diff *= bitDepthDiffWeighting; Double diffSq = diff * diff; #if JVET_V0056_MCTF || JVET_Y0077_BIM const Int index = std::min(3, std::abs(srcFrameInfo[i].origOffset) - 1); Double ww = 1, sw = 1; ww *= (noise < 25) ? 1 : 1.2; sw *= (noise < 25) ? 1.3 : 0.8; ww *= (error < 50) ? 1.2 : ((error > 100) ? 0.8 : 1); sw *= (error < 50) ? 1.3 : 1; ww *= ((minError + 1) / (error + 1)); const Double weight = weightScaling * s_refStrengths[refStrengthRow][index] * ww * exp(-diffSq / (2 * sw * sigmaSq)); #else const Int index = std::min(1, std::abs(srcFrameInfo[i].origOffset) - 1); const Double weight = weightScaling * s_refStrengths[refStrengthRow][index] * exp(-diffSq / (2 * sigmaSq)); #endif newVal += weight * refVal; temporalWeightSum += weight; } newVal /= temporalWeightSum; Pel sampleVal = (Pel)round(newVal); sampleVal=(sampleVal<0?0 : (sampleVal>maxSampleValue ? maxSampleValue : sampleVal)); *dstPel = sampleVal; } } } } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncTemporalFilter.h000066400000000000000000000160651442026013100222650ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncTemporalFilter.h \brief TEncTemporalFilter class (header) */ #ifndef __TEMPORAL_FILTER__ #define __TEMPORAL_FILTER__ #include "TLibCommon/TComPicYuv.h" #include "Utilities/TVideoIOYuv.h" #include #include #include //! \ingroup EncoderLib //! \{ struct MotionVector { Int x, y; Int error; #if JVET_V0056_MCTF || JVET_Y0077_BIM Int noise; MotionVector() : x(0), y(0), error(INT_LEAST32_MAX), noise(0) {} #else MotionVector() : x(0), y(0), error(INT_LEAST32_MAX) {} #endif void set(Int nx, Int ny, Int ne) { x = nx; y = ny; error = ne; } }; template struct Array2D { private: UInt m_width, m_height; std::vector< T > v; public: Array2D() : m_width(0), m_height(0), v() { } Array2D(UInt width, UInt height, const T& value=T()) : m_width(0), m_height(0), v() { allocate(width, height, value); } #if JVET_Y0077_BIM UInt w() const { return m_width; } UInt h() const { return m_height; } #endif Void allocate(UInt width, UInt height, const T& value=T()) { m_width=width; m_height=height; v.resize(std::size_t(m_width*m_height), value); } T& get(UInt x, UInt y) { assert(x mvs; Int origOffset; }; // ==================================================================================================================== // Class definition // ==================================================================================================================== class TEncTemporalFilter { public: TEncTemporalFilter(); ~TEncTemporalFilter() {} void init(const Int frameSkip, const Int inputBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int InternalBitDepth[MAX_NUM_CHANNEL_TYPE], const Int width, const Int height, const Int *pad, const Int frames, const Bool Rec709, const std::string &filename, const ChromaFormat inputChromaFormatIDC, const InputColourSpaceConversion colorSpaceConv, const Int qp, const Int GOPSize, const std::map &temporalFilterStrengths, const Int pastRefs, const Int futureRefs, const Int firstValidFrame, #if !JVET_Y0077_BIM const Int lastValidFrame); #else const Int lastValidFrame, const Bool mctfEnabled, std::map *adaptQPmap, const Bool bimEnabled); #endif Bool filter(TComPicYuv *orgPic, Int frame); private: // Private static member variables static const Double s_chromaFactor; static const Double s_sigmaMultiplier; static const Double s_sigmaZeroPoint; static const Int s_motionVectorFactor; static const Int s_padding; static const Int s_interpolationFilter[16][8]; #if JVET_V0056_MCTF static const Double s_refStrengths[2][4]; #else static const Double s_refStrengths[2][2]; #endif #if JVET_Y0077_BIM static const Int s_cuTreeThresh[4]; #endif // Private member variables Int m_FrameSkip; std::string m_inputFileName; Int m_inputBitDepth[MAX_NUM_CHANNEL_TYPE]; Int m_MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE]; Int m_internalBitDepth[MAX_NUM_CHANNEL_TYPE]; ChromaFormat m_chromaFormatIDC; Int m_sourceWidth; Int m_sourceHeight; Int m_QP; Int m_GOPSize; std::map m_temporalFilterStrengths; Int m_sourcePadding[2]; Int m_framesToBeEncoded; Bool m_bClipInputVideoToRec709Range; InputColourSpaceConversion m_inputColourSpaceConvert; Int m_pastRefs; Int m_futureRefs; Int m_firstValidFrame; Int m_lastValidFrame; #if JVET_Y0077_BIM Bool m_mctfEnabled; Bool m_bimEnabled; Int m_numCTU; std::map *m_ctuAdaptQP; #endif // Private functions Void subsampleLuma(const TComPicYuv &input, TComPicYuv &output, const Int factor = 2) const; Int motionErrorLuma(const TComPicYuv &orig, const TComPicYuv &buffer, const Int x, const Int y, Int dx, Int dy, const Int bs, const Int besterror = 8 * 8 * 1024 * 1024) const; Void motionEstimationLuma(Array2D &mvs, const TComPicYuv &orig, const TComPicYuv &buffer, const Int bs, const Array2D *previous=0, const Int factor = 1, const Bool doubleRes = false) const; Void motionEstimation(Array2D &mvs, const TComPicYuv &orgPic, const TComPicYuv &buffer, const TComPicYuv &origSubsampled2, const TComPicYuv &origSubsampled4) const; #if JVET_V0056_MCTF Void bilateralFilter(const TComPicYuv &orgPic, std::deque &srcFrameInfo, TComPicYuv &newOrgPic, Double overallStrength) const; #else Void bilateralFilter(const TComPicYuv &orgPic, const std::deque &srcFrameInfo, TComPicYuv &newOrgPic, Double overallStrength) const; #endif Void applyMotion(const Array2D &mvs, const TComPicYuv &input, TComPicYuv &output) const; }; // END CLASS DEFINITION TEncTemporalFilter //! \} #endif // __TEMPORAL_FILTER__ HM-HM-18.0/source/Lib/TLibEncoder/TEncTop.cpp000066400000000000000000001456651442026013100204420ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncTop.cpp \brief encoder class */ #include "TLibCommon/CommonDef.h" #include "TEncTop.h" #include "TEncPic.h" #include "TLibCommon/TComChromaFormat.h" #if FAST_BIT_EST #include "TLibCommon/ContextModel.h" #endif //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== TEncTop::TEncTop() : m_spsMap(MAX_NUM_SPS) , m_ppsMap(MAX_NUM_PPS) { m_iPOCLast = -1; m_iNumPicRcvd = 0; m_uiNumAllPicCoded = 0; m_pppcRDSbacCoder = NULL; m_pppcBinCoderCABAC = NULL; m_cRDGoOnSbacCoder.init( &m_cRDGoOnBinCoderCABAC ); #if ENC_DEC_TRACE if (g_hTrace == NULL) { g_hTrace = fopen( "TraceEnc.txt", "wb" ); } g_bJustDoIt = g_bEncDecTraceDisable; g_nSymbolCounter = 0; #endif m_iMaxRefPicNum = 0; #if FAST_BIT_EST ContextModel::buildNextStateTable(); #endif } TEncTop::~TEncTop() { #if ENC_DEC_TRACE if (g_hTrace != stdout) { fclose( g_hTrace ); } #endif } Void TEncTop::create () { // initialize global variables initROM(); // create processing unit classes m_cGOPEncoder. create( ); m_cSliceEncoder. create( getSourceWidth(), getSourceHeight(), m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth ); m_cCuEncoder. create( m_maxTotalCUDepth, m_maxCUWidth, m_maxCUHeight, m_chromaFormatIDC ); if (m_bUseSAO) { m_cEncSAO.create( getSourceWidth(), getSourceHeight(), m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA], m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA] ); m_cEncSAO.createEncData(getSaoCtuBoundary()); } #if ADAPTIVE_QP_SELECTION if (m_bUseAdaptQpSelect) { m_cTrQuant.initSliceQpDelta(); } #endif m_cLoopFilter.create( m_maxTotalCUDepth ); if ( m_RCEnableRateControl ) { #if JVET_Y0105_SW_AND_QDF m_cRateCtrl.init( m_framesToBeEncoded, m_RCTargetBitrate, (Int)( (Double)m_iFrameRate/m_temporalSubsampleRatio + 0.5), m_iGOPSize, m_uiIntraPeriod, m_iSourceWidth, m_iSourceHeight, m_maxCUWidth, m_maxCUHeight,m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList ); #else m_cRateCtrl.init( m_framesToBeEncoded, m_RCTargetBitrate, (Int)( (Double)m_iFrameRate/m_temporalSubsampleRatio + 0.5), m_iGOPSize, m_iSourceWidth, m_iSourceHeight, m_maxCUWidth, m_maxCUHeight,m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList ); #endif } m_pppcRDSbacCoder = new TEncSbac** [m_maxTotalCUDepth+1]; #if FAST_BIT_EST m_pppcBinCoderCABAC = new TEncBinCABACCounter** [m_maxTotalCUDepth+1]; #else m_pppcBinCoderCABAC = new TEncBinCABAC** [m_maxTotalCUDepth+1]; #endif for ( Int iDepth = 0; iDepth < m_maxTotalCUDepth+1; iDepth++ ) { m_pppcRDSbacCoder[iDepth] = new TEncSbac* [CI_NUM]; #if FAST_BIT_EST m_pppcBinCoderCABAC[iDepth] = new TEncBinCABACCounter* [CI_NUM]; #else m_pppcBinCoderCABAC[iDepth] = new TEncBinCABAC* [CI_NUM]; #endif for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ ) { m_pppcRDSbacCoder[iDepth][iCIIdx] = new TEncSbac; #if FAST_BIT_EST m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABACCounter; #else m_pppcBinCoderCABAC [iDepth][iCIIdx] = new TEncBinCABAC; #endif m_pppcRDSbacCoder [iDepth][iCIIdx]->init( m_pppcBinCoderCABAC [iDepth][iCIIdx] ); } } } Void TEncTop::destroy () { // destroy processing unit classes m_cGOPEncoder. destroy(); m_cSliceEncoder. destroy(); m_cCuEncoder. destroy(); m_cEncSAO. destroyEncData(); m_cEncSAO. destroy(); m_cLoopFilter. destroy(); m_cRateCtrl. destroy(); m_cSearch. destroy(); Int iDepth; for ( iDepth = 0; iDepth < m_maxTotalCUDepth+1; iDepth++ ) { for (Int iCIIdx = 0; iCIIdx < CI_NUM; iCIIdx ++ ) { delete m_pppcRDSbacCoder[iDepth][iCIIdx]; delete m_pppcBinCoderCABAC[iDepth][iCIIdx]; } } for ( iDepth = 0; iDepth < m_maxTotalCUDepth+1; iDepth++ ) { delete [] m_pppcRDSbacCoder[iDepth]; delete [] m_pppcBinCoderCABAC[iDepth]; } delete [] m_pppcRDSbacCoder; delete [] m_pppcBinCoderCABAC; // destroy ROM destroyROM(); return; } Void TEncTop::init(Bool isFieldCoding) { TComSPS &sps0=*(m_spsMap.allocatePS(0)); // NOTE: implementations that use more than 1 SPS need to be aware of activation issues. TComPPS &pps0=*(m_ppsMap.allocatePS(0)); // initialize SPS xInitSPS(sps0); xInitVPS(m_cVPS, sps0); if (m_RCCpbSaturationEnabled) { m_cRateCtrl.initHrdParam(sps0.getVuiParameters()->getHrdParameters(), m_iFrameRate, m_RCInitialCpbFullness); } m_cRdCost.setCostMode(m_costMode); // initialize PPS xInitPPS(pps0, sps0); xInitRPS(sps0, isFieldCoding); xInitScalingLists(sps0, pps0); if (m_wcgChromaQpControl.isEnabled()) { TComPPS &pps1=*(m_ppsMap.allocatePS(1)); xInitPPS(pps1, sps0); xInitScalingLists(sps0, pps1); } // initialize processing unit classes m_cGOPEncoder. init( this ); m_cSliceEncoder.init( this ); m_cCuEncoder. init( this ); m_cCuEncoder.setSliceEncoder(&m_cSliceEncoder); // initialize transform & quantization class m_pcCavlcCoder = getCavlcCoder(); m_cTrQuant.init( 1 << m_uiQuadtreeTULog2MaxSize, m_useRDOQ, m_useRDOQTS, m_useSelectiveRDOQ, true ,m_useTransformSkipFast #if ADAPTIVE_QP_SELECTION ,m_bUseAdaptQpSelect #endif ); // initialize encoder search class m_cSearch.init( this, &m_cTrQuant, m_iSearchRange, m_bipredSearchRange, m_motionEstimationSearchMethod, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cEntropyCoder, &m_cRdCost, getRDSbacCoder(), getRDGoOnSbacCoder() ); m_iMaxRefPicNum = 0; } Void TEncTop::xInitScalingLists(TComSPS &sps, TComPPS &pps) { // Initialise scaling lists // The encoder will only use the SPS scaling lists. The PPS will never be marked present. const Int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE] = { sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_LUMA), sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_CHROMA) }; if(getUseScalingListId() == SCALING_LIST_OFF) { getTrQuant()->setFlatScalingList(maxLog2TrDynamicRange, sps.getBitDepths()); getTrQuant()->setUseScalingList(false); sps.setScalingListPresentFlag(false); pps.setScalingListPresentFlag(false); } else if(getUseScalingListId() == SCALING_LIST_DEFAULT) { sps.getScalingList().setDefaultScalingList (); sps.setScalingListPresentFlag(false); pps.setScalingListPresentFlag(false); getTrQuant()->setScalingList(&(sps.getScalingList()), maxLog2TrDynamicRange, sps.getBitDepths()); getTrQuant()->setUseScalingList(true); } else if(getUseScalingListId() == SCALING_LIST_FILE_READ) { sps.getScalingList().setDefaultScalingList (); if(sps.getScalingList().xParseScalingList(getScalingListFileName())) { Bool bParsedScalingList=false; // Use of boolean so that assertion outputs useful string assert(bParsedScalingList); exit(1); } sps.getScalingList().checkDcOfMatrix(); sps.setScalingListPresentFlag(sps.getScalingList().checkDefaultScalingList()); pps.setScalingListPresentFlag(false); getTrQuant()->setScalingList(&(sps.getScalingList()), maxLog2TrDynamicRange, sps.getBitDepths()); getTrQuant()->setUseScalingList(true); } else { printf("error : ScalingList == %d not supported\n",getUseScalingListId()); assert(0); } if (getUseScalingListId() != SCALING_LIST_OFF) { // Prepare delta's: for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { const Int predListStep = (sizeId == SCALING_LIST_32x32? (SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) : 1); // if 32x32, skip over chroma entries. for(UInt listId = 0; listId < SCALING_LIST_NUM; listId+=predListStep) { sps.getScalingList().checkPredMode( sizeId, listId ); } } } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== Void TEncTop::deletePicBuffer() { TComList::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for ( Int i = 0; i < iSize; i++ ) { TComPic* pcPic = *(iterPic++); pcPic->destroy(); delete pcPic; pcPic = NULL; } } /** - Application has picture buffer list with size of GOP + 1 - Picture buffer list acts like as ring buffer - End of the list has the latest picture . \param flush cause encoder to encode a partial GOP \param pcPicYuvOrg original YUV picture \param pcPicYuvTrueOrg \param snrCSC \retval rcListPicYuvRecOut list of reconstruction YUV pictures \retval accessUnitsOut list of output access units \retval iNumEncoded number of encoded pictures */ #if JVET_X0048_X0103_FILM_GRAIN Void TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, TComPicYuv* pcfilteredOrgPicForFG, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded) #else Void TEncTop::encode( Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded ) #endif { if (pcPicYuvOrg != NULL) { // get original YUV TComPic* pcPicCurr = NULL; Int ppsID=-1; // Use default PPS ID if (getWCGChromaQPControl().isEnabled()) { ppsID=getdQPs()[ m_iPOCLast+1 ]; } xGetNewPicBuffer( pcPicCurr, ppsID ); pcPicYuvOrg->copyToPic( pcPicCurr->getPicYuvOrg() ); pcPicYuvTrueOrg->copyToPic( pcPicCurr->getPicYuvTrueOrg() ); #if JVET_X0048_X0103_FILM_GRAIN if (m_fgcSEIAnalysisEnabled && m_fgcSEIExternalDenoised.empty()) { pcfilteredOrgPicForFG->copyToPic(pcPicCurr->getPicFilteredFG()); } #endif #if SHUTTER_INTERVAL_SEI_PROCESSING if ( getShutterFilterFlag() ) { pcPicCurr->xOutputPreFilteredPic(pcPicCurr, &m_cListPic); pcPicCurr->getPicYuvOrg()->copyToPic(pcPicYuvOrg); } #endif // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast( pcPicCurr ) ); } } if ((m_iNumPicRcvd == 0) || (!flush && (m_iPOCLast != 0) && (m_iNumPicRcvd != m_iGOPSize) && (m_iGOPSize != 0))) { iNumEncoded = 0; return; } if ( m_RCEnableRateControl ) { m_cRateCtrl.initRCGOP( m_iNumPicRcvd ); } // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, false, false, ipCSC, snrCSC, getOutputLogControl()); if ( m_RCEnableRateControl ) { m_cRateCtrl.destroyRCGOP(); } iNumEncoded = m_iNumPicRcvd; m_iNumPicRcvd = 0; m_uiNumAllPicCoded += iNumEncoded; } /**------------------------------------------------ Separate interlaced frame into two fields -------------------------------------------------**/ Void separateFields(Pel* org, Pel* dstField, UInt stride, UInt width, UInt height, Bool isTop) { if (!isTop) { org += stride; } for (Int y = 0; y < height>>1; y++) { for (Int x = 0; x < width; x++) { dstField[x] = org[x]; } dstField += stride; org += stride*2; } } Void TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded, Bool isTff) { iNumEncoded = 0; for (Int fieldNum=0; fieldNum<2; fieldNum++) { if (pcPicYuvOrg) { /* -- field initialization -- */ const Bool isTopField=isTff==(fieldNum==0); TComPic *pcField; xGetNewPicBuffer( pcField, -1 ); pcField->setReconMark (false); // where is this normally? if (fieldNum==1) // where is this normally? { TComPicYuv* rpcPicYuvRec; // org. buffer if ( rcListPicYuvRecOut.size() >= (UInt)m_iGOPSize+1 ) // need to maintain field 0 in list of RecOuts while processing field 1. Hence +1 on m_iGOPSize. { rpcPicYuvRec = rcListPicYuvRecOut.popFront(); } else { rpcPicYuvRec = new TComPicYuv; rpcPicYuvRec->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, true); } rcListPicYuvRecOut.pushBack( rpcPicYuvRec ); } pcField->getSlice(0)->setPOC( m_iPOCLast ); // superfluous? #if !REDUCED_ENCODER_MEMORY pcField->getPicYuvRec()->setBorderExtension(false);// where is this normally? #endif pcField->setTopField(isTopField); // interlaced requirement for (UInt componentIndex = 0; componentIndex < pcPicYuvOrg->getNumberValidComponents(); componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt stride = pcPicYuvOrg->getStride(component); separateFields((pcPicYuvOrg->getBuf(component) + pcPicYuvOrg->getMarginX(component) + (pcPicYuvOrg->getMarginY(component) * stride)), pcField->getPicYuvOrg()->getAddr(component), pcPicYuvOrg->getStride(component), pcPicYuvOrg->getWidth(component), pcPicYuvOrg->getHeight(component), isTopField); separateFields((pcPicYuvTrueOrg->getBuf(component) + pcPicYuvTrueOrg->getMarginX(component) + (pcPicYuvTrueOrg->getMarginY(component) * stride)), pcField->getPicYuvTrueOrg()->getAddr(component), pcPicYuvTrueOrg->getStride(component), pcPicYuvTrueOrg->getWidth(component), pcPicYuvTrueOrg->getHeight(component), isTopField); } // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast( pcField ) ); } } if ( m_iNumPicRcvd && ((flush&&fieldNum==1) || (m_iPOCLast/2)==0 || m_iNumPicRcvd==m_iGOPSize ) ) { // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, true, isTff, ipCSC, snrCSC, getOutputLogControl()); iNumEncoded += m_iNumPicRcvd; m_uiNumAllPicCoded += m_iNumPicRcvd; m_iNumPicRcvd = 0; } } } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== /** - Application has picture buffer list with size of GOP + 1 - Picture buffer list acts like as ring buffer - End of the list has the latest picture . \retval rpcPic obtained picture buffer */ Void TEncTop::xGetNewPicBuffer ( TComPic*& rpcPic, Int ppsId ) { rpcPic=0; // At this point, the SPS and PPS can be considered activated - they are copied to the new TComPic. const TComPPS *pPPS=(ppsId<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsId); assert (pPPS!=0); const TComPPS &pps=*pPPS; const TComSPS *pSPS=m_spsMap.getPS(pps.getSPSId()); assert (pSPS!=0); const TComSPS &sps=*pSPS; TComSlice::sortPicList(m_cListPic); // use an entry in the buffered list if the maximum number that need buffering has been reached: if (m_cListPic.size() >= (UInt)(m_iGOPSize + getMaxDecPicBuffering(MAX_TLAYER-1) + 2) ) { TComList::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for ( Int i = 0; i < iSize; i++ ) { rpcPic = *iterPic; if(rpcPic->getSlice(0)->isReferenced() == false) { break; } iterPic++; } // If PPS ID is the same, we will assume that it has not changed since it was last used // and return the old object. if (pps.getPPSId() == rpcPic->getPicSym()->getPPS().getPPSId()) { #if REDUCED_ENCODER_MEMORY rpcPic->releaseAllReconstructionData(); #if JVET_X0048_X0103_FILM_GRAIN rpcPic->prepareForEncoderSourcePicYuv( getFilmGrainAnalysisEnabled() ); #else rpcPic->prepareForEncoderSourcePicYuv(); #endif #endif } else { // the IDs differ - free up an entry in the list, and then create a new one, as with the case where the max buffering state has not been reached. delete rpcPic; m_cListPic.erase(iterPic); rpcPic=0; } } if (rpcPic==0) { if ( getUseAdaptiveQP() ) { TEncPic* pcEPic = new TEncPic; #if REDUCED_ENCODER_MEMORY pcEPic->create(sps, pps, pps.getMaxCuDQPDepth() + 1 #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , getFilmGrainAnalysisEnabled() #endif ); #else pcEPic->create( sps, pps, pps.getMaxCuDQPDepth() + 1, false #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , getFilmGrainAnalysisEnabled() #endif ); #endif rpcPic = pcEPic; } else { rpcPic = new TComPic; #if REDUCED_ENCODER_MEMORY rpcPic->create( sps, pps, true, false #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , getFilmGrainAnalysisEnabled() #endif ); #else rpcPic->create( sps, pps, false #if SHUTTER_INTERVAL_SEI_PROCESSING , getShutterFilterFlag() #endif #if JVET_X0048_X0103_FILM_GRAIN , getFilmGrainAnalysisEnabled() #endif ); #endif } m_cListPic.pushBack( rpcPic ); } rpcPic->setReconMark (false); m_iPOCLast++; m_iNumPicRcvd++; rpcPic->getSlice(0)->setPOC( m_iPOCLast ); #if !REDUCED_ENCODER_MEMORY // mark it should be extended rpcPic->getPicYuvRec()->setBorderExtension(false); #endif } Void TEncTop::xInitVPS(TComVPS &vps, const TComSPS &sps) { // The SPS must have already been set up. // set the VPS profile information. *vps.getPTL() = *sps.getPTL(); vps.setMaxOpSets(1); vps.getTimingInfo()->setTimingInfoPresentFlag ( false ); vps.setNumHrdParameters( 0 ); vps.createHrdParamBuffer(); for( UInt i = 0; i < vps.getNumHrdParameters(); i ++ ) { vps.setHrdOpSetIdx( 0, i ); vps.setCprmsPresentFlag( false, i ); // Set up HrdParameters here. } } Void TEncTop::xInitSPS(TComSPS &sps) { ProfileTierLevel& profileTierLevel = *sps.getPTL()->getGeneralPTL(); profileTierLevel.setLevelIdc(m_level); profileTierLevel.setTierFlag(m_levelTier); profileTierLevel.setProfileIdc(m_profile); profileTierLevel.setProfileCompatibilityFlag(m_profile, 1); profileTierLevel.setProgressiveSourceFlag(m_progressiveSourceFlag); profileTierLevel.setInterlacedSourceFlag(m_interlacedSourceFlag); profileTierLevel.setNonPackedConstraintFlag(m_nonPackedConstraintFlag); profileTierLevel.setFrameOnlyConstraintFlag(m_frameOnlyConstraintFlag); profileTierLevel.setBitDepthConstraint(m_bitDepthConstraintValue); profileTierLevel.setChromaFormatConstraint(m_chromaFormatConstraintValue); profileTierLevel.setIntraConstraintFlag(m_intraConstraintFlag); profileTierLevel.setOnePictureOnlyConstraintFlag(m_onePictureOnlyConstraintFlag); profileTierLevel.setLowerBitRateConstraintFlag(m_lowerBitRateConstraintFlag); if ((m_profile == Profile::MAIN10) && (m_bitDepth[CHANNEL_TYPE_LUMA] == 8) && (m_bitDepth[CHANNEL_TYPE_CHROMA] == 8)) { /* The above constraint is equal to Profile::MAIN */ profileTierLevel.setProfileCompatibilityFlag(Profile::MAIN, 1); } if (m_profile == Profile::MAIN) { /* A Profile::MAIN10 decoder can always decode Profile::MAIN */ profileTierLevel.setProfileCompatibilityFlag(Profile::MAIN10, 1); } /* XXX: should Main be marked as compatible with still picture? */ /* XXX: may be a good idea to refactor the above into a function * that chooses the actual compatibility based upon options */ sps.setPicWidthInLumaSamples ( m_iSourceWidth ); sps.setPicHeightInLumaSamples ( m_iSourceHeight ); sps.setConformanceWindow ( m_conformanceWindow ); sps.setMaxCUWidth ( m_maxCUWidth ); sps.setMaxCUHeight ( m_maxCUHeight ); sps.setMaxTotalCUDepth ( m_maxTotalCUDepth ); sps.setChromaFormatIdc( m_chromaFormatIDC); sps.setLog2DiffMaxMinCodingBlockSize(m_log2DiffMaxMinCodingBlockSize); Int minCUSize = sps.getMaxCUWidth() >> ( sps.getLog2DiffMaxMinCodingBlockSize() ); Int log2MinCUSize = 0; while(minCUSize > 1) { minCUSize >>= 1; log2MinCUSize++; } sps.setLog2MinCodingBlockSize(log2MinCUSize); sps.setPCMLog2MinSize (m_uiPCMLog2MinSize); sps.setUsePCM ( m_usePCM ); sps.setPCMLog2MaxSize( m_pcmLog2MaxSize ); sps.setQuadtreeTULog2MaxSize( m_uiQuadtreeTULog2MaxSize ); sps.setQuadtreeTULog2MinSize( m_uiQuadtreeTULog2MinSize ); sps.setQuadtreeTUMaxDepthInter( m_uiQuadtreeTUMaxDepthInter ); sps.setQuadtreeTUMaxDepthIntra( m_uiQuadtreeTUMaxDepthIntra ); sps.setSPSTemporalMVPEnabledFlag((getTMVPModeId() == 2 || getTMVPModeId() == 1)); sps.setMaxTrSize ( 1 << m_uiQuadtreeTULog2MaxSize ); sps.setUseAMP ( m_useAMP ); for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { sps.setBitDepth (ChannelType(channelType), m_bitDepth[channelType] ); #if O0043_BEST_EFFORT_DECODING sps.setStreamBitDepth(ChannelType(channelType), m_bitDepth[channelType] ); #endif sps.setQpBDOffset (ChannelType(channelType), (6 * (m_bitDepth[channelType] - 8))); sps.setPCMBitDepth (ChannelType(channelType), m_PCMBitDepth[channelType] ); } sps.setUseSAO( m_bUseSAO ); sps.setMaxTLayers( m_maxTempLayer ); sps.setTemporalIdNestingFlag( ( m_maxTempLayer == 1 ) ? true : false ); for (Int i = 0; i < min(sps.getMaxTLayers(),(UInt) MAX_TLAYER); i++ ) { sps.setMaxDecPicBuffering(m_maxDecPicBuffering[i], i); sps.setNumReorderPics(m_numReorderPics[i], i); } sps.setPCMFilterDisableFlag ( m_bPCMFilterDisableFlag ); sps.setScalingListFlag ( (m_useScalingListId == SCALING_LIST_OFF) ? 0 : 1 ); sps.setUseStrongIntraSmoothing( m_useStrongIntraSmoothing ); sps.setVuiParametersPresentFlag(getVuiParametersPresentFlag()); if (sps.getVuiParametersPresentFlag()) { TComVUI* pcVUI = sps.getVuiParameters(); pcVUI->setAspectRatioInfoPresentFlag(getAspectRatioInfoPresentFlag()); pcVUI->setAspectRatioIdc(getAspectRatioIdc()); pcVUI->setSarWidth(getSarWidth()); pcVUI->setSarHeight(getSarHeight()); pcVUI->setOverscanInfoPresentFlag(getOverscanInfoPresentFlag()); pcVUI->setOverscanAppropriateFlag(getOverscanAppropriateFlag()); pcVUI->setVideoSignalTypePresentFlag(getVideoSignalTypePresentFlag()); pcVUI->setVideoFormat(getVideoFormat()); pcVUI->setVideoFullRangeFlag(getVideoFullRangeFlag()); pcVUI->setColourDescriptionPresentFlag(getColourDescriptionPresentFlag()); pcVUI->setColourPrimaries(getColourPrimaries()); pcVUI->setTransferCharacteristics(getTransferCharacteristics()); pcVUI->setMatrixCoefficients(getMatrixCoefficients()); pcVUI->setChromaLocInfoPresentFlag(getChromaLocInfoPresentFlag()); pcVUI->setChromaSampleLocTypeTopField(getChromaSampleLocTypeTopField()); pcVUI->setChromaSampleLocTypeBottomField(getChromaSampleLocTypeBottomField()); pcVUI->setNeutralChromaIndicationFlag(getNeutralChromaIndicationFlag()); pcVUI->setDefaultDisplayWindow(getDefaultDisplayWindow()); pcVUI->setFrameFieldInfoPresentFlag(getFrameFieldInfoPresentFlag()); pcVUI->setFieldSeqFlag(false); pcVUI->setHrdParametersPresentFlag(false); pcVUI->getTimingInfo()->setPocProportionalToTimingFlag(getPocProportionalToTimingFlag()); pcVUI->getTimingInfo()->setNumTicksPocDiffOneMinus1 (getNumTicksPocDiffOneMinus1() ); pcVUI->setBitstreamRestrictionFlag(getBitstreamRestrictionFlag()); pcVUI->setTilesFixedStructureFlag(getTilesFixedStructureFlag()); pcVUI->setMotionVectorsOverPicBoundariesFlag(getMotionVectorsOverPicBoundariesFlag()); pcVUI->setMinSpatialSegmentationIdc(getMinSpatialSegmentationIdc()); pcVUI->setMaxBytesPerPicDenom(getMaxBytesPerPicDenom()); pcVUI->setMaxBitsPerMinCuDenom(getMaxBitsPerMinCuDenom()); pcVUI->setLog2MaxMvLengthHorizontal(getLog2MaxMvLengthHorizontal()); pcVUI->setLog2MaxMvLengthVertical(getLog2MaxMvLengthVertical()); } sps.setNumLongTermRefPicSPS(NUM_LONG_TERM_REF_PIC_SPS); assert (NUM_LONG_TERM_REF_PIC_SPS <= MAX_NUM_LONG_TERM_REF_PICS); for (Int k = 0; k < NUM_LONG_TERM_REF_PIC_SPS; k++) { sps.setLtRefPicPocLsbSps(k, 0); sps.setUsedByCurrPicLtSPSFlag(k, 0); } if( getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() || getCpbSaturationEnabled() ) { xInitHrdParameters(sps); } if( getBufferingPeriodSEIEnabled() || getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() ) { sps.getVuiParameters()->setHrdParametersPresentFlag( true ); } // Set up SPS range extension settings sps.getSpsRangeExtension().setTransformSkipRotationEnabledFlag(m_transformSkipRotationEnabledFlag); sps.getSpsRangeExtension().setTransformSkipContextEnabledFlag(m_transformSkipContextEnabledFlag); for (UInt signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++) { sps.getSpsRangeExtension().setRdpcmEnabledFlag(RDPCMSignallingMode(signallingModeIndex), m_rdpcmEnabledFlag[signallingModeIndex]); } sps.getSpsRangeExtension().setExtendedPrecisionProcessingFlag(m_extendedPrecisionProcessingFlag); sps.getSpsRangeExtension().setIntraSmoothingDisabledFlag( m_intraSmoothingDisabledFlag ); sps.getSpsRangeExtension().setHighPrecisionOffsetsEnabledFlag(m_highPrecisionOffsetsEnabledFlag); sps.getSpsRangeExtension().setPersistentRiceAdaptationEnabledFlag(m_persistentRiceAdaptationEnabledFlag); sps.getSpsRangeExtension().setCabacBypassAlignmentEnabledFlag(m_cabacBypassAlignmentEnabledFlag); } // calculate scale value of bitrate and initial delay Int calcScale(Int x) { if (x==0) { return 0; } UInt iMask = 0xffffffff; Int ScaleValue = 32; while ((x&iMask) != 0) { ScaleValue--; iMask = (iMask >> 1); } return ScaleValue; } Void TEncTop::xInitHrdParameters(TComSPS &sps) { Bool useSubCpbParams = (getSliceMode() > 0) || (getSliceSegmentMode() > 0); Int bitRate = getTargetBitrate(); Bool isRandomAccess = getIntraPeriod() > 0; Int cpbSize = getCpbSize(); assert (cpbSize!=0); // CPB size may not be equal to zero. ToDo: have a better default and check for level constraints if( !getVuiParametersPresentFlag() && !getCpbSaturationEnabled() ) { return; } TComVUI *vui = sps.getVuiParameters(); TComHRD *hrd = vui->getHrdParameters(); TimingInfo *timingInfo = vui->getTimingInfo(); timingInfo->setTimingInfoPresentFlag( true ); switch( getFrameRate() ) { case 24: timingInfo->setNumUnitsInTick( 1125000 ); timingInfo->setTimeScale ( 27000000 ); break; case 25: timingInfo->setNumUnitsInTick( 1080000 ); timingInfo->setTimeScale ( 27000000 ); break; case 30: timingInfo->setNumUnitsInTick( 900900 ); timingInfo->setTimeScale ( 27000000 ); break; case 50: timingInfo->setNumUnitsInTick( 540000 ); timingInfo->setTimeScale ( 27000000 ); break; case 60: timingInfo->setNumUnitsInTick( 450450 ); timingInfo->setTimeScale ( 27000000 ); break; default: timingInfo->setNumUnitsInTick( 1001 ); timingInfo->setTimeScale ( 60000 ); break; } if (getTemporalSubsampleRatio()>1) { UInt temporalSubsampleRatio = getTemporalSubsampleRatio(); if ( Double(timingInfo->getNumUnitsInTick()) * temporalSubsampleRatio > std::numeric_limits::max() ) { timingInfo->setTimeScale( timingInfo->getTimeScale() / temporalSubsampleRatio ); } else { timingInfo->setNumUnitsInTick( timingInfo->getNumUnitsInTick() * temporalSubsampleRatio ); } } Bool rateCnt = ( bitRate > 0 ); hrd->setNalHrdParametersPresentFlag( rateCnt ); hrd->setVclHrdParametersPresentFlag( rateCnt ); hrd->setSubPicCpbParamsPresentFlag( useSubCpbParams ); if( hrd->getSubPicCpbParamsPresentFlag() ) { hrd->setTickDivisorMinus2( 100 - 2 ); // hrd->setDuCpbRemovalDelayLengthMinus1( 7 ); // 8-bit precision ( plus 1 for last DU in AU ) hrd->setSubPicCpbParamsInPicTimingSEIFlag( true ); hrd->setDpbOutputDelayDuLengthMinus1( 5 + 7 ); // With sub-clock tick factor of 100, at least 7 bits to have the same value as AU dpb delay } else { hrd->setSubPicCpbParamsInPicTimingSEIFlag( false ); } if (calcScale(bitRate) <= 6) { hrd->setBitRateScale(0); } else { hrd->setBitRateScale(calcScale(bitRate) - 6); } if (calcScale(cpbSize) <= 4) { hrd->setCpbSizeScale(0); } else { hrd->setCpbSizeScale(calcScale(cpbSize) - 4); } hrd->setDuCpbSizeScale( 6 ); // in units of 2^( 4 + 6 ) = 1,024 bit hrd->setInitialCpbRemovalDelayLengthMinus1(15); // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit if( isRandomAccess ) { hrd->setCpbRemovalDelayLengthMinus1(5); // 32 = 2^5 (plus 1) hrd->setDpbOutputDelayLengthMinus1 (5); // 32 + 3 = 2^6 } else { hrd->setCpbRemovalDelayLengthMinus1(9); // max. 2^10 hrd->setDpbOutputDelayLengthMinus1 (9); // max. 2^10 } // Note: parameters for all temporal layers are initialized with the same values Int i, j; UInt bitrateValue, cpbSizeValue; UInt duCpbSizeValue; UInt duBitRateValue = 0; for( i = 0; i < MAX_TLAYER; i ++ ) { hrd->setFixedPicRateFlag( i, 1 ); hrd->setPicDurationInTcMinus1( i, 0 ); hrd->setLowDelayHrdFlag( i, 0 ); hrd->setCpbCntMinus1( i, 0 ); //! \todo check for possible PTL violations // BitRate[ i ] = ( bit_rate_value_minus1[ i ] + 1 ) * 2^( 6 + bit_rate_scale ) bitrateValue = bitRate / (1 << (6 + hrd->getBitRateScale()) ); // bitRate is in bits, so it needs to be scaled down // CpbSize[ i ] = ( cpb_size_value_minus1[ i ] + 1 ) * 2^( 4 + cpb_size_scale ) cpbSizeValue = cpbSize / (1 << (4 + hrd->getCpbSizeScale()) ); // using bitRate results in 1 second CPB size // DU CPB size could be smaller (i.e. bitrateValue / number of DUs), but we don't know // in how many DUs the slice segment settings will result duCpbSizeValue = bitrateValue; duBitRateValue = cpbSizeValue; for( j = 0; j < ( hrd->getCpbCntMinus1( i ) + 1 ); j ++ ) { hrd->setBitRateValueMinus1( i, j, 0, ( bitrateValue - 1 ) ); hrd->setCpbSizeValueMinus1( i, j, 0, ( cpbSizeValue - 1 ) ); hrd->setDuCpbSizeValueMinus1( i, j, 0, ( duCpbSizeValue - 1 ) ); hrd->setDuBitRateValueMinus1( i, j, 0, ( duBitRateValue - 1 ) ); hrd->setCbrFlag( i, j, 0, false ); hrd->setBitRateValueMinus1( i, j, 1, ( bitrateValue - 1) ); hrd->setCpbSizeValueMinus1( i, j, 1, ( cpbSizeValue - 1 ) ); hrd->setDuCpbSizeValueMinus1( i, j, 1, ( duCpbSizeValue - 1 ) ); hrd->setDuBitRateValueMinus1( i, j, 1, ( duBitRateValue - 1 ) ); hrd->setCbrFlag( i, j, 1, false ); } } } Void TEncTop::xInitPPS(TComPPS &pps, const TComSPS &sps) { // pps ID already initialised. pps.setSPSId(sps.getSPSId()); pps.setConstrainedIntraPred( m_bUseConstrainedIntraPred ); Bool bUseDQP = (getMaxCuDQPDepth() > 0)? true : false; if((getMaxDeltaQP() != 0 )|| getUseAdaptiveQP()) { bUseDQP = true; } if ( getLumaLevelToDeltaQPMapping().isEnabled() ) { bUseDQP = true; } #if JVET_V0078 if (getSmoothQPReductionEnable()) { bUseDQP = true; } #endif #if JVET_Y0077_BIM if (m_bimEnabled) { bUseDQP = true; } #endif if (m_costMode==COST_SEQUENCE_LEVEL_LOSSLESS || m_costMode==COST_LOSSLESS_CODING) { bUseDQP=false; } if ( m_RCEnableRateControl ) { pps.setUseDQP(true); pps.setMaxCuDQPDepth( 0 ); } else if(bUseDQP) { pps.setUseDQP(true); pps.setMaxCuDQPDepth( m_iMaxCuDQPDepth ); } else { pps.setUseDQP(false); pps.setMaxCuDQPDepth( 0 ); } if ( m_diffCuChromaQpOffsetDepth >= 0 ) { pps.getPpsRangeExtension().setDiffCuChromaQpOffsetDepth(m_diffCuChromaQpOffsetDepth); pps.getPpsRangeExtension().clearChromaQpOffsetList(); pps.getPpsRangeExtension().setChromaQpOffsetListEntry(1, 6, 6); /* todo, insert table entries from command line (NB, 0 should not be touched) */ } else { pps.getPpsRangeExtension().setDiffCuChromaQpOffsetDepth(0); pps.getPpsRangeExtension().clearChromaQpOffsetList(); } pps.getPpsRangeExtension().setCrossComponentPredictionEnabledFlag(m_crossComponentPredictionEnabledFlag); pps.getPpsRangeExtension().setLog2SaoOffsetScale(CHANNEL_TYPE_LUMA, m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA ]); pps.getPpsRangeExtension().setLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA, m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA]); if (getWCGChromaQPControl().isEnabled()) { const Int baseQp=m_iQP+pps.getPPSId(); const Double chromaQp = m_wcgChromaQpControl.chromaQpScale * baseQp + m_wcgChromaQpControl.chromaQpOffset; const Double dcbQP = m_wcgChromaQpControl.chromaCbQpScale * chromaQp; const Double dcrQP = m_wcgChromaQpControl.chromaCrQpScale * chromaQp; const Int cbQP =(Int)(dcbQP + ( dcbQP < 0 ? -0.5 : 0.5) ); const Int crQP =(Int)(dcrQP + ( dcrQP < 0 ? -0.5 : 0.5) ); pps.setQpOffset(COMPONENT_Cb, Clip3( -12, 12, min(0, cbQP) + m_chromaCbQpOffset )); pps.setQpOffset(COMPONENT_Cr, Clip3( -12, 12, min(0, crQP) + m_chromaCrQpOffset)); } else { pps.setQpOffset(COMPONENT_Cb, m_chromaCbQpOffset ); pps.setQpOffset(COMPONENT_Cr, m_chromaCrQpOffset ); } Bool bChromaDeltaQPEnabled = false; { bChromaDeltaQPEnabled = ( m_sliceChromaQpOffsetIntraOrPeriodic[0] || m_sliceChromaQpOffsetIntraOrPeriodic[1] ); if( !bChromaDeltaQPEnabled ) { for( Int i=0; i 0 || m_iNumRowsMinus1 > 0) ); pps.setUseWP( m_useWeightedPred ); pps.setWPBiPred( m_useWeightedBiPred ); pps.setOutputFlagPresentFlag( false ); pps.setSignDataHidingEnabledFlag(getSignDataHidingEnabledFlag()); if ( getDeblockingFilterMetric() ) { pps.setDeblockingFilterOverrideEnabledFlag(true); pps.setPPSDeblockingFilterDisabledFlag(false); } else { pps.setDeblockingFilterOverrideEnabledFlag( !getLoopFilterOffsetInPPS() ); pps.setPPSDeblockingFilterDisabledFlag( getLoopFilterDisable() ); } if (! pps.getPPSDeblockingFilterDisabledFlag()) { pps.setDeblockingFilterBetaOffsetDiv2( getLoopFilterBetaOffset() ); pps.setDeblockingFilterTcOffsetDiv2( getLoopFilterTcOffset() ); } else { pps.setDeblockingFilterBetaOffsetDiv2(0); pps.setDeblockingFilterTcOffsetDiv2(0); } // deblockingFilterControlPresentFlag is true if any of the settings differ from the inferred values: const Bool deblockingFilterControlPresentFlag = pps.getDeblockingFilterOverrideEnabledFlag() || pps.getPPSDeblockingFilterDisabledFlag() || pps.getDeblockingFilterBetaOffsetDiv2() != 0 || pps.getDeblockingFilterTcOffsetDiv2() != 0; pps.setDeblockingFilterControlPresentFlag(deblockingFilterControlPresentFlag); pps.setLog2ParallelMergeLevelMinus2 (m_log2ParallelMergeLevelMinus2 ); pps.setCabacInitPresentFlag(CABAC_INIT_PRESENT_FLAG); pps.setLoopFilterAcrossSlicesEnabledFlag( m_bLFCrossSliceBoundaryFlag ); Int histogram[MAX_NUM_REF + 1]; for( Int i = 0; i <= MAX_NUM_REF; i++ ) { histogram[i]=0; } for( Int i = 0; i < getGOPSize(); i++) { assert(getGOPEntry(i).m_numRefPicsActive >= 0 && getGOPEntry(i).m_numRefPicsActive <= MAX_NUM_REF); histogram[getGOPEntry(i).m_numRefPicsActive]++; } Int maxHist=-1; Int bestPos=0; for( Int i = 0; i <= MAX_NUM_REF; i++ ) { if(histogram[i]>maxHist) { maxHist=histogram[i]; bestPos=i; } } assert(bestPos <= 15); pps.setNumRefIdxL0DefaultActive(bestPos); pps.setNumRefIdxL1DefaultActive(bestPos); pps.setTransquantBypassEnabledFlag(getTransquantBypassEnabledFlag()); pps.setUseTransformSkip( m_useTransformSkip ); pps.getPpsRangeExtension().setLog2MaxTransformSkipBlockSize( m_log2MaxTransformSkipBlockSize ); if (m_sliceSegmentMode != NO_SLICES) { pps.setDependentSliceSegmentsEnabledFlag( true ); } xInitPPSforTiles(pps); } //Function for initializing m_RPSList, a list of TComReferencePictureSet, based on the GOPEntry objects read from the config file. Void TEncTop::xInitRPS(TComSPS &sps, Bool isFieldCoding) { TComReferencePictureSet* rps; sps.createRPSList(getGOPSize() + m_extraRPSs + 1); TComRPSList* rpsList = sps.getRPSList(); for( Int i = 0; i < getGOPSize()+m_extraRPSs; i++) { const GOPEntry &ge = getGOPEntry(i); rps = rpsList->getReferencePictureSet(i); rps->setNumberOfPictures(ge.m_numRefPics); rps->setNumRefIdc(ge.m_numRefIdc); Int numNeg = 0; Int numPos = 0; for( Int j = 0; j < ge.m_numRefPics; j++) { rps->setDeltaPOC(j,ge.m_referencePics[j]); rps->setUsed(j,ge.m_usedByCurrPic[j]); if(ge.m_referencePics[j]>0) { numPos++; } else { numNeg++; } } rps->setNumberOfNegativePictures(numNeg); rps->setNumberOfPositivePictures(numPos); // handle inter RPS intialization from the config file. rps->setInterRPSPrediction(ge.m_interRPSPrediction > 0); // not very clean, converting anything > 0 to true. rps->setDeltaRIdxMinus1(0); // index to the Reference RPS is always the previous one. TComReferencePictureSet* RPSRef = i>0 ? rpsList->getReferencePictureSet(i-1): NULL; // get the reference RPS if (ge.m_interRPSPrediction == 2) // Automatic generation of the inter RPS idc based on the RIdx provided. { assert (RPSRef!=NULL); Int deltaRPS = getGOPEntry(i-1).m_POC - ge.m_POC; // the ref POC - current POC Int numRefDeltaPOC = RPSRef->getNumberOfPictures(); rps->setDeltaRPS(deltaRPS); // set delta RPS rps->setNumRefIdc(numRefDeltaPOC+1); // set the numRefIdc to the number of pictures in the reference RPS + 1. Int count=0; for (Int j = 0; j <= numRefDeltaPOC; j++ ) // cycle through pics in reference RPS. { Int RefDeltaPOC = (jgetDeltaPOC(j): 0; // if it is the last decoded picture, set RefDeltaPOC = 0 rps->setRefIdc(j, 0); for (Int k = 0; k < rps->getNumberOfPictures(); k++ ) // cycle through pics in current RPS. { if (rps->getDeltaPOC(k) == ( RefDeltaPOC + deltaRPS)) // if the current RPS has a same picture as the reference RPS. { rps->setRefIdc(j, (rps->getUsed(k)?1:2)); count++; break; } } } if (count != rps->getNumberOfPictures()) { printf("Warning: Unable fully predict all delta POCs using the reference RPS index given in the config file. Setting Inter RPS to false for this RPS.\n"); rps->setInterRPSPrediction(0); } } else if (ge.m_interRPSPrediction == 1) // inter RPS idc based on the RefIdc values provided in config file. { assert (RPSRef!=NULL); rps->setDeltaRPS(ge.m_deltaRPS); rps->setNumRefIdc(ge.m_numRefIdc); for (Int j = 0; j < ge.m_numRefIdc; j++ ) { rps->setRefIdc(j, ge.m_refIdc[j]); } // the following code overwrite the deltaPOC and Used by current values read from the config file with the ones // computed from the RefIdc. A warning is printed if they are not identical. numNeg = 0; numPos = 0; TComReferencePictureSet RPSTemp; // temporary variable for (Int j = 0; j < ge.m_numRefIdc; j++ ) { if (ge.m_refIdc[j]) { Int deltaPOC = ge.m_deltaRPS + ((j < RPSRef->getNumberOfPictures())? RPSRef->getDeltaPOC(j) : 0); RPSTemp.setDeltaPOC((numNeg+numPos),deltaPOC); RPSTemp.setUsed((numNeg+numPos),ge.m_refIdc[j]==1?1:0); if (deltaPOC<0) { numNeg++; } else { numPos++; } } } if (numNeg != rps->getNumberOfNegativePictures()) { printf("Warning: number of negative pictures in RPS is different between intra and inter RPS specified in the config file.\n"); rps->setNumberOfNegativePictures(numNeg); rps->setNumberOfPictures(numNeg+numPos); } if (numPos != rps->getNumberOfPositivePictures()) { printf("Warning: number of positive pictures in RPS is different between intra and inter RPS specified in the config file.\n"); rps->setNumberOfPositivePictures(numPos); rps->setNumberOfPictures(numNeg+numPos); } RPSTemp.setNumberOfPictures(numNeg+numPos); RPSTemp.setNumberOfNegativePictures(numNeg); RPSTemp.sortDeltaPOC(); // sort the created delta POC before comparing // check if Delta POC and Used are the same // print warning if they are not. for (Int j = 0; j < ge.m_numRefIdc; j++ ) { if (RPSTemp.getDeltaPOC(j) != rps->getDeltaPOC(j)) { printf("Warning: delta POC is different between intra RPS and inter RPS specified in the config file.\n"); rps->setDeltaPOC(j,RPSTemp.getDeltaPOC(j)); } if (RPSTemp.getUsed(j) != rps->getUsed(j)) { printf("Warning: Used by Current in RPS is different between intra and inter RPS specified in the config file.\n"); rps->setUsed(j,RPSTemp.getUsed(j)); } } } } //In case of field coding, we need to set special parameters for the first bottom field of the sequence, since it is not specified in the cfg file. //The position = GOPSize + extraRPSs which is (a priori) unused is reserved for this field in the RPS. if (isFieldCoding) { rps = rpsList->getReferencePictureSet(getGOPSize()+m_extraRPSs); rps->setNumberOfPictures(1); rps->setNumberOfNegativePictures(1); rps->setNumberOfPositivePictures(0); rps->setNumberOfLongtermPictures(0); rps->setDeltaPOC(0,-1); rps->setPOC(0,0); rps->setUsed(0,true); rps->setInterRPSPrediction(false); rps->setDeltaRIdxMinus1(0); rps->setDeltaRPS(0); rps->setNumRefIdc(0); } } // This is a function that // determines what Reference Picture Set to use // for a specific slice (with POC = POCCurr) Void TEncTop::selectReferencePictureSet(TComSlice* slice, Int POCCurr, Int GOPid ) { slice->setRPSidx(GOPid); for(Int extraNum=m_iGOPSize; extraNum 0 && getDecodingRefreshType() > 0) { Int POCIndex = POCCurr%m_uiIntraPeriod; if(POCIndex == 0) { POCIndex = m_uiIntraPeriod; } if(POCIndex == m_GOPList[extraNum].m_POC) { slice->setRPSidx(extraNum); } } else { if(POCCurr==m_GOPList[extraNum].m_POC) { slice->setRPSidx(extraNum); } } } if(POCCurr == 1 && slice->getPic()->isField()) { slice->setRPSidx(m_iGOPSize+m_extraRPSs); } const TComReferencePictureSet *rps = (slice->getSPS()->getRPSList()->getReferencePictureSet(slice->getRPSidx())); slice->setRPS(rps); } Int TEncTop::getReferencePictureSetIdxForSOP(Int POCCurr, Int GOPid ) { Int rpsIdx = GOPid; for(Int extraNum=m_iGOPSize; extraNum 0 && getDecodingRefreshType() > 0) { Int POCIndex = POCCurr%m_uiIntraPeriod; if(POCIndex == 0) { POCIndex = m_uiIntraPeriod; } if(POCIndex == m_GOPList[extraNum].m_POC) { rpsIdx = extraNum; } } else { if(POCCurr==m_GOPList[extraNum].m_POC) { rpsIdx = extraNum; } } } return rpsIdx; } Void TEncTop::xInitPPSforTiles(TComPPS &pps) { pps.setTileUniformSpacingFlag( m_tileUniformSpacingFlag ); pps.setNumTileColumnsMinus1( m_iNumColumnsMinus1 ); pps.setNumTileRowsMinus1( m_iNumRowsMinus1 ); if( !m_tileUniformSpacingFlag ) { pps.setTileColumnWidth( m_tileColumnWidth ); pps.setTileRowHeight( m_tileRowHeight ); } pps.setLoopFilterAcrossTilesEnabledFlag( m_loopFilterAcrossTilesEnabledFlag ); // # substreams is "per tile" when tiles are independent. } Void TEncCfg::xCheckGSParameters() { Int iWidthInCU = ( m_iSourceWidth%m_maxCUWidth ) ? m_iSourceWidth/m_maxCUWidth + 1 : m_iSourceWidth/m_maxCUWidth; Int iHeightInCU = ( m_iSourceHeight%m_maxCUHeight ) ? m_iSourceHeight/m_maxCUHeight + 1 : m_iSourceHeight/m_maxCUHeight; UInt uiCummulativeColumnWidth = 0; UInt uiCummulativeRowHeight = 0; //check the column relative parameters if( m_iNumColumnsMinus1 >= (1<<(LOG2_MAX_NUM_COLUMNS_MINUS1+1)) ) { printf( "The number of columns is larger than the maximum allowed number of columns.\n" ); exit( EXIT_FAILURE ); } if( m_iNumColumnsMinus1 >= iWidthInCU ) { printf( "The current picture can not have so many columns.\n" ); exit( EXIT_FAILURE ); } if( m_iNumColumnsMinus1 && !m_tileUniformSpacingFlag ) { for(Int i=0; i= iWidthInCU ) { printf( "The width of the column is too large.\n" ); exit( EXIT_FAILURE ); } } //check the row relative parameters if( m_iNumRowsMinus1 >= (1<<(LOG2_MAX_NUM_ROWS_MINUS1+1)) ) { printf( "The number of rows is larger than the maximum allowed number of rows.\n" ); exit( EXIT_FAILURE ); } if( m_iNumRowsMinus1 >= iHeightInCU ) { printf( "The current picture can not have so many rows.\n" ); exit( EXIT_FAILURE ); } if( m_iNumRowsMinus1 && !m_tileUniformSpacingFlag ) { for(Int i=0; i= iHeightInCU ) { printf( "The height of the row is too large.\n" ); exit( EXIT_FAILURE ); } } } Void TEncTop::setParamSetChanged(Int spsId, Int ppsId) { m_ppsMap.setChangedFlag(ppsId); m_spsMap.setChangedFlag(spsId); } Bool TEncTop::PPSNeedsWriting(Int ppsId) { Bool bChanged=m_ppsMap.getChangedFlag(ppsId); m_ppsMap.clearChangedFlag(ppsId); return bChanged; } Bool TEncTop::SPSNeedsWriting(Int spsId) { Bool bChanged=m_spsMap.getChangedFlag(spsId); m_spsMap.clearChangedFlag(spsId); return bChanged; } Int TEncCfg::getQPForPicture(const UInt gopIndex, const TComSlice *pSlice) const { const Int lumaQpBDOffset = pSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA); Int qp; if (getCostMode()==COST_LOSSLESS_CODING) { qp=LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP; } else { const SliceType sliceType=pSlice->getSliceType(); qp = getBaseQP(); // modify QP if a fractional QP was originally specified, cause dQPs to be 0 or 1. const Int* pdQPs = getdQPs(); if ( pdQPs ) { qp += pdQPs[ pSlice->getPOC() ]; } if(sliceType==I_SLICE) { qp += getIntraQPOffset(); } else { // Only adjust QP when not lossless #if JVET_Y0077_BIM if (!((getMaxDeltaQP() == 0) && (!getLumaLevelToDeltaQPMapping().isEnabled()) && (!getSmoothQPReductionEnable()) && (!getBIM()) && (qp == -lumaQpBDOffset) && (pSlice->getPPS()->getTransquantBypassEnabledFlag()))) #else #if JVET_V0078 if (!((getMaxDeltaQP() == 0) && (!getLumaLevelToDeltaQPMapping().isEnabled()) && (!getSmoothQPReductionEnable()) && (qp == -lumaQpBDOffset) && (pSlice->getPPS()->getTransquantBypassEnabledFlag()))) #else if (!(( getMaxDeltaQP() == 0 ) && (!getLumaLevelToDeltaQPMapping().isEnabled()) && (qp == -lumaQpBDOffset ) && (pSlice->getPPS()->getTransquantBypassEnabledFlag()))) #endif #endif { const GOPEntry &gopEntry=getGOPEntry(gopIndex); // adjust QP according to the QP offset for the GOP entry. qp +=gopEntry.m_QPOffset; // adjust QP according to QPOffsetModel for the GOP entry. Double dqpOffset=qp*gopEntry.m_QPOffsetModelScale+gopEntry.m_QPOffsetModelOffset+0.5; Int qpOffset = (Int)floor(Clip3(0.0, 3.0, dqpOffset)); qp += qpOffset ; } } } qp = Clip3( -lumaQpBDOffset, MAX_QP, qp ); return qp; } //! \} HM-HM-18.0/source/Lib/TLibEncoder/TEncTop.h000066400000000000000000000250701442026013100200720ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file TEncTop.h \brief encoder class (header) */ #ifndef __TENCTOP__ #define __TENCTOP__ // Include files #include "TLibCommon/TComList.h" #include "TLibCommon/TComPrediction.h" #include "TLibCommon/TComTrQuant.h" #include "TLibCommon/TComLoopFilter.h" #include "TLibCommon/AccessUnit.h" #include "Utilities/TVideoIOYuv.h" #include "TEncCfg.h" #include "TEncGOP.h" #include "TEncSlice.h" #include "TEncEntropy.h" #include "TEncCavlc.h" #include "TEncSbac.h" #include "TEncSearch.h" #include "TEncSampleAdaptiveOffset.h" #include "TEncPreanalyzer.h" #include "TEncRateCtrl.h" //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== /// encoder class class TEncTop : public TEncCfg { private: // picture Int m_iPOCLast; ///< time index (POC) Int m_iNumPicRcvd; ///< number of received pictures UInt m_uiNumAllPicCoded; ///< number of coded pictures TComList m_cListPic; ///< dynamic list of pictures // encoder search TEncSearch m_cSearch; ///< encoder search class //TEncEntropy* m_pcEntropyCoder; ///< entropy encoder TEncCavlc* m_pcCavlcCoder; ///< CAVLC encoder // coding tool TComTrQuant m_cTrQuant; ///< transform & quantization class TComLoopFilter m_cLoopFilter; ///< deblocking filter class TEncSampleAdaptiveOffset m_cEncSAO; ///< sample adaptive offset class TEncEntropy m_cEntropyCoder; ///< entropy encoder TEncCavlc m_cCavlcCoder; ///< CAVLC encoder TEncSbac m_cSbacCoder; ///< SBAC encoder TEncBinCABAC m_cBinCoderCABAC; ///< bin coder CABAC // processing unit TEncGOP m_cGOPEncoder; ///< GOP encoder TEncSlice m_cSliceEncoder; ///< slice encoder TEncCu m_cCuEncoder; ///< CU encoder // SPS ParameterSetMap m_spsMap; ///< SPS. This is the base value. This is copied to TComPicSym ParameterSetMap m_ppsMap; ///< PPS. This is the base value. This is copied to TComPicSym // RD cost computation TComRdCost m_cRdCost; ///< RD cost computation class TEncSbac*** m_pppcRDSbacCoder; ///< temporal storage for RD computation TEncSbac m_cRDGoOnSbacCoder; ///< going on SBAC model for RD stage #if FAST_BIT_EST TEncBinCABACCounter*** m_pppcBinCoderCABAC; ///< temporal CABAC state storage for RD computation TEncBinCABACCounter m_cRDGoOnBinCoderCABAC; ///< going on bin coder CABAC for RD stage #else TEncBinCABAC*** m_pppcBinCoderCABAC; ///< temporal CABAC state storage for RD computation TEncBinCABAC m_cRDGoOnBinCoderCABAC; ///< going on bin coder CABAC for RD stage #endif // quality control TEncPreanalyzer m_cPreanalyzer; ///< image characteristics analyzer for TM5-step3-like adaptive QP TEncRateCtrl m_cRateCtrl; ///< Rate control class protected: Void xGetNewPicBuffer ( TComPic*& rpcPic, Int ppsId ); ///< get picture buffer which will be processed. If ppsId<0, then the ppsMap will be queried for the first match. Void xInitVPS (TComVPS &vps, const TComSPS &sps); ///< initialize VPS from encoder options Void xInitSPS (TComSPS &sps); ///< initialize SPS from encoder options Void xInitPPS (TComPPS &pps, const TComSPS &sps); ///< initialize PPS from encoder options Void xInitScalingLists (TComSPS &sps, TComPPS &pps); ///< initialize scaling lists Void xInitHrdParameters(TComSPS &sps); ///< initialize HRD parameters Void xInitPPSforTiles (TComPPS &pps); Void xInitRPS (TComSPS &sps, Bool isFieldCoding); ///< initialize PPS from encoder options public: TEncTop(); virtual ~TEncTop(); Void create (); Void destroy (); Void init (Bool isFieldCoding); Void deletePicBuffer (); // ------------------------------------------------------------------------------------------------------------------- // member access functions // ------------------------------------------------------------------------------------------------------------------- TComList* getListPic () { return &m_cListPic; } TEncSearch* getPredSearch () { return &m_cSearch; } TComTrQuant* getTrQuant () { return &m_cTrQuant; } TComLoopFilter* getLoopFilter () { return &m_cLoopFilter; } TEncSampleAdaptiveOffset* getSAO () { return &m_cEncSAO; } TEncGOP* getGOPEncoder () { return &m_cGOPEncoder; } TEncSlice* getSliceEncoder () { return &m_cSliceEncoder; } TEncCu* getCuEncoder () { return &m_cCuEncoder; } TEncEntropy* getEntropyCoder () { return &m_cEntropyCoder; } TEncCavlc* getCavlcCoder () { return &m_cCavlcCoder; } TEncSbac* getSbacCoder () { return &m_cSbacCoder; } TEncBinCABAC* getBinCABAC () { return &m_cBinCoderCABAC; } TComRdCost* getRdCost () { return &m_cRdCost; } TEncSbac*** getRDSbacCoder () { return m_pppcRDSbacCoder; } TEncSbac* getRDGoOnSbacCoder () { return &m_cRDGoOnSbacCoder; } TEncRateCtrl* getRateCtrl () { return &m_cRateCtrl; } Void selectReferencePictureSet(TComSlice* slice, Int POCCurr, Int GOPid ); Int getReferencePictureSetIdxForSOP(Int POCCurr, Int GOPid ); Void setParamSetChanged(Int spsId, Int ppsId); Bool PPSNeedsWriting(Int ppsId); Bool SPSNeedsWriting(Int spsId); // ------------------------------------------------------------------------------------------------------------------- // encoder function // ------------------------------------------------------------------------------------------------------------------- /// encode several number of pictures until end-of-sequence #if JVET_X0048_X0103_FILM_GRAIN Void encode(Bool bEos, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, TComPicYuv* pcfilteredOrgPicForFG, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, // used for SNR calculations. Picture in original colour space. TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded); #else Void encode( Bool bEos, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, // used for SNR calculations. Picture in original colour space. TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded ); #endif /// encode several number of pictures until end-of-sequence Void encode( Bool bEos, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, // used for SNR calculations. Picture in original colour space. TComList& rcListPicYuvRecOut, std::list& accessUnitsOut, Int& iNumEncoded, Bool isTff); TEncAnalyze::OutputLogControl getOutputLogControl() const { TEncAnalyze::OutputLogControl outputLogCtrl; outputLogCtrl.printFrameMSE=m_printFrameMSE; outputLogCtrl.printMSEBasedSNR=m_printMSEBasedSequencePSNR; outputLogCtrl.printMSSSIM=m_printMSSSIM; outputLogCtrl.printSequenceMSE=m_printSequenceMSE; outputLogCtrl.printXPSNR=m_bXPSNREnableFlag; outputLogCtrl.printHexPerPOCPSNRs=m_printHexPsnr; return outputLogCtrl; } Void printSummary(Bool isField) { m_cGOPEncoder.printOutSummary (m_uiNumAllPicCoded, isField, getOutputLogControl(), m_spsMap.getFirstPS()->getBitDepths()); } }; //! \} #endif // __TENCTOP__ HM-HM-18.0/source/Lib/TLibEncoder/WeightPredAnalysis.cpp000066400000000000000000000674651442026013100226750ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file WeightPredAnalysis.cpp \brief weighted prediction encoder class */ #include "../TLibCommon/CommonDef.h" #include "../TLibCommon/TComSlice.h" #include "../TLibCommon/TComPic.h" #include "../TLibCommon/TComPicYuv.h" #include "WeightPredAnalysis.h" #include static const Double WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD=0.99; // NOTE: U0040 used 0.95 //! calculate SAD values for both WP version and non-WP version. static Int64 xCalcSADvalueWP(const Int bitDepth, const Pel *pOrgPel, const Pel *pRefPel, const Int width, const Int height, const Int orgStride, const Int refStride, const Int log2Denom, const Int weight, const Int offset, const Bool useHighPrecision); //! calculate SAD values for both WP version and non-WP version. static Int64 xCalcSADvalueWPOptionalClip(const Int bitDepth, const Pel *pOrgPel, const Pel *pRefPel, const Int width, const Int height, const Int orgStride, const Int refStride, const Int log2Denom, const Int weight, const Int offset, const Bool useHighPrecision, const Bool clipped); // ----------------------------------------------------------------------------- // Helper functions //! calculate Histogram for array of pixels static Void xCalcHistogram(const Pel *pPel, std::vector &histogram, const Int width, const Int height, const Int stride, const Int maxPel) { histogram.clear(); histogram.resize(maxPel); for( Int y = 0; y < height; y++ ) { for( Int x = 0; x < width; x++ ) { const Pel v=pPel[x]; histogram[v<0?0:(v>=maxPel)?maxPel-1:v]++; } pPel += stride; } } static Distortion xCalcHistDistortion (const std::vector &histogram0, const std::vector &histogram1) { Distortion distortion = 0; assert(histogram0.size()==histogram1.size()); const Int numElements=Int(histogram0.size()); // Scan histograms to compute histogram distortion for (Int i = 0; i <= numElements; i++) { distortion += (Distortion)(abs(histogram0[i] - histogram1[i])); } return distortion; } static void xScaleHistogram(const std::vector &histogramInput, std::vector &histogramOutput, // cannot be the same as the input const Int bitDepth, const Int log2Denom, const Int weight, const Int offset, const Bool bHighPrecision) { assert(&histogramInput != &histogramOutput); const Int numElements=Int(histogramInput.size()); histogramOutput.clear(); histogramOutput.resize(numElements); const Int64 iRealLog2Denom = bHighPrecision ? 0 : (bitDepth - 8); const Int64 iRealOffset = ((Int64)offset)<> log2Denom) + iRealOffset)); histogramOutput[j] += histogramInput[i]; } } static Distortion xSearchHistogram(const std::vector &histogramSource, const std::vector &histogramRef, std::vector &outputHistogram, const Int bitDepth, const Int log2Denom, Int &weightToUpdate, Int &offsetToUpdate, const Bool bHighPrecision, const ComponentID compID) { const Int initialWeight = weightToUpdate; const Int initialOffset = offsetToUpdate; const Int weightRange = 10; const Int offsetRange = 10; const Int maxOffset = 1 << ((bHighPrecision == true) ? (bitDepth - 1) : 7); const Int range = bHighPrecision ? (1<(initialWeight - weightRange, defaultWeight - range); const Int maxSearchWeight = std::min(initialWeight + weightRange+1, defaultWeight + range); Distortion minDistortion = std::numeric_limits::max(); Int bestWeight = initialWeight; Int bestOffset = initialOffset; for (Int searchWeight = minSearchWeight; searchWeight < maxSearchWeight; searchWeight++) { if (compID == COMPONENT_Y) { for (Int searchOffset = std::max(initialOffset - offsetRange, -maxOffset); searchOffset <= initialOffset + offsetRange && searchOffset<=(maxOffset-1); searchOffset++) { xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, searchOffset, bHighPrecision); const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram); if (distortion < minDistortion) { minDistortion = distortion; bestWeight = searchWeight; bestOffset = searchOffset; } } } else { const Int pred = ( maxOffset - ( ( maxOffset*searchWeight)>>(log2Denom) ) ); for (Int searchOffset = initialOffset - offsetRange; searchOffset <= initialOffset + offsetRange; searchOffset++) { const Int deltaOffset = Clip3( -4*maxOffset, 4*maxOffset-1, (searchOffset - pred) ); // signed 10bit (if !bHighPrecision) const Int clippedOffset = Clip3( -1*maxOffset, 1*maxOffset-1, (deltaOffset + pred) ); // signed 8bit (if !bHighPrecision) xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, clippedOffset, bHighPrecision); const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram); if (distortion < minDistortion) { minDistortion = distortion; bestWeight = searchWeight; bestOffset = clippedOffset; } } } } weightToUpdate = bestWeight; offsetToUpdate = bestOffset; // regenerate best histogram xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, bestWeight, bestOffset, bHighPrecision); return minDistortion; } // ----------------------------------------------------------------------------- // Member functions WeightPredAnalysis::WeightPredAnalysis() { for ( UInt lst =0 ; lstbPresentFlag = false; pwp->uiLog2WeightDenom = 0; pwp->iWeight = 1; pwp->iOffset = 0; } } } } //! calculate AC and DC values for current original image Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice) { //===== calculate AC/DC value ===== TComPicYuv* pPic = slice->getPic()->getPicYuvOrg(); WPACDCParam weightACDCParam[MAX_NUM_COMPONENT]; for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) { const ComponentID compID = ComponentID(componentIndex); // calculate DC/AC value for channel const Int stride = pPic->getStride(compID); const Int width = pPic->getWidth(compID); const Int height = pPic->getHeight(compID); const Int sample = width*height; Int64 orgDC = 0; { const Pel *pPel = pPic->getAddr(compID); for(Int y = 0; y < height; y++, pPel+=stride ) { for(Int x = 0; x < width; x++ ) { orgDC += (Int)( pPel[x] ); } } } const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample); Int64 orgAC = 0; { const Pel *pPel = pPic->getAddr(compID); for(Int y = 0; y < height; y++, pPel += stride ) { for(Int x = 0; x < width; x++ ) { orgAC += abs( (Int)pPel[x] - (Int)orgNormDC ); } } } const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0; weightACDCParam[compID].iDC = (((orgDC<>1)) / sample); weightACDCParam[compID].iAC = orgAC; } slice->setWpAcDcParam(weightACDCParam); } //! check weighted pred or non-weighted pred Void WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice) { const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg(); Int presentCnt = 0; for ( UInt lst=0 ; lstgetNumberValidComponents(); componentIndex++) { WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); presentCnt += (Int)pwp->bPresentFlag; } } } if(presentCnt==0) { slice->setTestWeightPred(false); slice->setTestWeightBiPred(false); for ( UInt lst=0 ; lstgetNumberValidComponents(); componentIndex++) { WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); pwp->bPresentFlag = false; pwp->uiLog2WeightDenom = 0; pwp->iWeight = 1; pwp->iOffset = 0; } } } slice->setWpScaling( m_wp ); } else { slice->setTestWeightPred (slice->getPPS()->getUseWP()); slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred()); } } //! estimate wp tables for explicit wp Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method) { Int iDenom = 6; Bool validRangeFlag = false; if(slice->getNumRefIdx(REF_PIC_LIST_0)>3) { iDenom = 7; } do { validRangeFlag = xUpdatingWPParameters(slice, iDenom); if (!validRangeFlag) { iDenom--; // decrement to satisfy the range limitation } } while (validRangeFlag == false); // selecting whether WP is used, or not (fast search) // NOTE: This is not operating on a slice, but the entire picture. switch (method) { case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT: xSelectWP(slice, iDenom); break; case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT: xSelectWPHistExtClip(slice, iDenom, false, false, false); break; case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT: xSelectWPHistExtClip(slice, iDenom, false, false, true); break; case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING: xSelectWPHistExtClip(slice, iDenom, false, true, true); break; case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION: xSelectWPHistExtClip(slice, iDenom, true, true, true); break; default: assert(0); exit(1); } slice->setWpScaling( m_wp ); } //! update wp tables for explicit wp w.r.t range limitation Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom) { const Int numComp = slice->getPic()->getPicYuvOrg()->getNumberValidComponents(); const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); const Int numPredDir = slice->isInterP() ? 1 : 2; assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); for ( Int refList = 0; refList < numPredDir; refList++ ) { const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) { WPACDCParam *currWeightACDCParam, *refWeightACDCParam; slice->getWpAcDcParam(currWeightACDCParam); slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam); for ( Int comp = 0; comp < numComp; comp++ ) { const ComponentID compID = ComponentID(comp); const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); const Int range = bUseHighPrecisionWeighting ? (1<> realLog2Denom ); Int clippedOffset; if(isChroma(compID)) // Chroma offset range limination { const Int pred = ( range - ( ( range*weight)>>(log2Denom) ) ); const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) ); // signed 8bit } else // Luma offset range limitation { clippedOffset = Clip3( -range, range-1, offset); } // Weighting factor limitation const Int defaultWeight = (1<= range || deltaWeight < -range) { return false; } m_wp[refList][refIdxTemp][comp].bPresentFlag = true; m_wp[refList][refIdxTemp][comp].iWeight = weight; m_wp[refList][refIdxTemp][comp].iOffset = clippedOffset; m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom; } } } return true; } /** select whether weighted pred enables or not. * \param TComSlice *slice * \param log2Denom * \returns Bool */ Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram) { const TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); const Int defaultWeight = 1<isInterP() ? 1 : 2; const Bool useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); for ( Int refList = 0; refList < numPredDir; refList++ ) { const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) { Bool useChromaWeight = false; for(Int comp=0; compgetNumberValidComponents(); comp++) { const ComponentID compID = ComponentID(comp); const Pel *pOrg = pPic->getAddr(compID); const Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); const Int orgStride = pPic->getStride(compID); const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); const Int width = pPic->getWidth(compID); const Int height = pPic->getHeight(compID); const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); WPScalingParam &wp = m_wp[refList][refIdxTemp][compID]; Int weight = wp.iWeight; Int offset = wp.iOffset; Int weightDef = defaultWeight; Int offsetDef = 0; // calculate SAD costs with/without wp for luma const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP); if (SADnoWP > 0) { const Int64 SADWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision, bClipInitialSADWP); const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP; Double dRatioSr0SAD = std::numeric_limits::max(); Double dRatioSrSAD = std::numeric_limits::max(); if (bUseHistogram) { std::vector histogramOrg;// = pPic->getHistogram(compID); std::vector histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID); std::vector searchedHistogram; // Compute histograms xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth); xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth); // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID); // calculate updated WP SAD const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision); dRatioSrSAD = (Double)SADSrWP / (Double)SADnoWP; if (bDoEnhancement) { // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID); // calculate updated WP SAD const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision); dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP; } } if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) { wp.bPresentFlag = false; wp.iOffset = 0; wp.iWeight = defaultWeight; wp.uiLog2WeightDenom = log2Denom; } else { if (compID != COMPONENT_Y) { useChromaWeight = true; } if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD) { wp.bPresentFlag = true; wp.iOffset = offsetDef; wp.iWeight = weightDef; wp.uiLog2WeightDenom = log2Denom; } else if (dRatioSrSAD < dRatioSAD) { wp.bPresentFlag = true; wp.iOffset = offset; wp.iWeight = weight; wp.uiLog2WeightDenom = log2Denom; } } } else // (SADnoWP <= 0) { wp.bPresentFlag = false; wp.iOffset = 0; wp.iWeight = defaultWeight; wp.uiLog2WeightDenom = log2Denom; } } for(Int comp=1; compgetNumberValidComponents(); comp++) { m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight; } } } return true; } //! select whether weighted pred enables or not. Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom) { TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); const Int defaultWeight = 1<isInterP() ? 1 : 2; const Bool useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); for ( Int refList = 0; refList < numPredDir; refList++ ) { const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) { Int64 SADWP = 0, SADnoWP = 0; for(Int comp=0; compgetNumberValidComponents(); comp++) { const ComponentID compID = ComponentID(comp); Pel *pOrg = pPic->getAddr(compID); Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); const Int orgStride = pPic->getStride(compID); const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); const Int width = pPic->getWidth(compID); const Int height = pPic->getHeight(compID); const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); // calculate SAD costs with/without wp for luma SADWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting); SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting); } const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits::max(); if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) { for(Int comp=0; compgetNumberValidComponents(); comp++) { WPScalingParam &wp=m_wp[refList][refIdxTemp][comp]; wp.bPresentFlag = false; wp.iOffset = 0; wp.iWeight = defaultWeight; wp.uiLog2WeightDenom = log2Denom; } } } } return true; } // Alternatively, a SSE-based measure could be used instead. // The respective function has been removed as it currently redundant. static Int64 xCalcSADvalueWP(const Int bitDepth, const Pel *pOrgPel, const Pel *pRefPel, const Int width, const Int height, const Int orgStride, const Int refStride, const Int log2Denom, const Int weight, const Int offset, const Bool useHighPrecision) { //const Int64 iSize = iWidth*iHeight; const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); const Int64 realOffset = ((Int64)offset)<> (Int64) log2Denom) + realOffset); SAD += abs((Int64)pOrgPel[x] - scaledValue); } pOrgPel += orgStride; pRefPel += refStride; } } else { //const Int64 iSize = iWidth*iHeight; const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); const Int64 realOffset = ((Int64)offset)< #include #include #include #include #include #include #include "TLibCommon/TComRom.h" #include "TVideoIOYuv.h" using namespace std; // ==================================================================================================================== // Local Functions // ==================================================================================================================== /** * Scale all pixels in img depending upon sign of shiftbits by a factor of * 2shiftbits. * * @param img pointer to image to be transformed * @param stride distance between vertically adjacent pixels of img. * @param width width of active area in img. * @param height height of active area in img. * @param shiftbits if zero, no operation performed * if > 0, multiply by 2shiftbits, see scalePlane() * if < 0, divide and round by 2shiftbits and clip, * see invScalePlane(). * @param minval minimum clipping value when dividing. * @param maxval maximum clipping value when dividing. */ static Void scalePlane(Pel* img, const UInt stride, const UInt width, const UInt height, Int shiftbits, Pel minval, Pel maxval) { if (shiftbits > 0) { for (UInt y = 0; y < height; y++, img+=stride) { for (UInt x = 0; x < width; x++) { img[x] <<= shiftbits; } } } else if (shiftbits < 0) { shiftbits=-shiftbits; Pel rounding = 1 << (shiftbits-1); for (UInt y = 0; y < height; y++, img+=stride) { for (UInt x = 0; x < width; x++) { img[x] = Clip3(minval, maxval, Pel((img[x] + rounding) >> shiftbits)); } } } } static Void copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane); // ==================================================================================================================== // Public member functions // ==================================================================================================================== /** * Open file for reading/writing Y'CbCr frames. * * Frames read/written have bitdepth fileBitDepth, and are automatically * formatted as 8 or 16 bit word values (see TVideoIOYuv::write()). * * Image data read or written is converted to/from internalBitDepth * (See scalePlane(), TVideoIOYuv::read() and TVideoIOYuv::write() for * further details). * * \param pchFile file name string * \param bWriteMode file open mode: true=write, false=read * \param fileBitDepth bit-depth array of input/output file data. * \param MSBExtendedBitDepth * \param internalBitDepth bit-depth array to scale image data to/from when reading/writing. */ Void TVideoIOYuv::open( const std::string &fileName, Bool bWriteMode, const Int fileBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int internalBitDepth[MAX_NUM_CHANNEL_TYPE] ) { //NOTE: files cannot have bit depth greater than 16 for(UInt ch=0; ch(fileBitDepth[ch], 16); m_MSBExtendedBitDepth[ch] = MSBExtendedBitDepth[ch]; m_bitdepthShift [ch] = internalBitDepth[ch] - m_MSBExtendedBitDepth[ch]; if (m_fileBitdepth[ch] > 16) { if (bWriteMode) { std::cerr << "\nWARNING: Cannot write a yuv file of bit depth greater than 16 - output will be right-shifted down to 16-bit precision\n" << std::endl; } else { std::cerr << "\nERROR: Cannot read a yuv file of bit depth greater than 16\n" << std::endl; exit(0); } } } if ( bWriteMode ) { m_cHandle.open( fileName.c_str(), ios::binary | ios::out ); if( m_cHandle.fail() ) { printf("\nfailed to write reconstructed YUV file\n"); exit(0); } } else { m_cHandle.open( fileName.c_str(), ios::binary | ios::in ); if( m_cHandle.fail() ) { printf("\nfailed to open Input YUV file\n"); exit(0); } } return; } Void TVideoIOYuv::close() { m_cHandle.close(); } Bool TVideoIOYuv::isEof() { return m_cHandle.eof(); } Bool TVideoIOYuv::isFail() { return m_cHandle.fail(); } /** * Skip numFrames in input. * * This function correctly handles cases where the input file is not * seekable, by consuming bytes. */ Void TVideoIOYuv::skipFrames(Int numFrames, UInt width, UInt height, ChromaFormat format) { if (numFrames==0) { return; } //------------------ //set the frame size according to the chroma format streamoff frameSize = 0; UInt wordsize=1; // default to 8-bit, unless a channel with more than 8-bits is detected. for (UInt component = 0; component < getNumberValidComponents(format); component++) { ComponentID compID=ComponentID(component); frameSize += (width >> getComponentScaleX(compID, format)) * (height >> getComponentScaleY(compID, format)); if (m_fileBitdepth[toChannelType(compID)] > 8) { wordsize=2; } } frameSize *= wordsize; //------------------ const streamoff offset = frameSize * numFrames; /* attempt to seek */ if (!!m_cHandle.seekg(offset, ios::cur)) { return; /* success */ } m_cHandle.clear(); /* fall back to consuming the input */ TChar buf[512]; const streamoff offset_mod_bufsize = offset % sizeof(buf); for (streamoff i = 0; i < offset - offset_mod_bufsize; i += sizeof(buf)) { m_cHandle.read(buf, sizeof(buf)); } m_cHandle.read(buf, offset_mod_bufsize); } /** * Read width*height pixels from fd into dst, optionally * padding the left and right edges by edge-extension. Input may be * either 8bit or 16bit little-endian lsb-aligned words. * * @param dst destination image plane * @param fd input file stream * @param is16bit true if input file carries > 8bit data, false otherwise. * @param stride444 distance between vertically adjacent pixels of dst. * @param width444 width of active area in dst. * @param height444 height of active area in dst. * @param pad_x444 length of horizontal padding. * @param pad_y444 length of vertical padding. * @param compID chroma component * @param destFormat chroma format of image * @param fileFormat chroma format of file * @param fileBitDepth component bit depth in file * @return true for success, false in case of error */ static Bool readPlane(Pel* dst, istream& fd, Bool is16bit, UInt stride444, UInt width444, UInt height444, UInt pad_x444, UInt pad_y444, const ComponentID compID, const ChromaFormat destFormat, const ChromaFormat fileFormat, const UInt fileBitDepth) { const UInt csx_file =getComponentScaleX(compID, fileFormat); const UInt csy_file =getComponentScaleY(compID, fileFormat); const UInt csx_dest =getComponentScaleX(compID, destFormat); const UInt csy_dest =getComponentScaleY(compID, destFormat); const UInt width_dest = width444 >>csx_dest; const UInt height_dest = height444>>csy_dest; const UInt pad_x_dest = pad_x444>>csx_dest; const UInt pad_y_dest = pad_y444>>csy_dest; const UInt stride_dest = stride444>>csx_dest; const UInt full_width_dest = width_dest+pad_x_dest; const UInt full_height_dest = height_dest+pad_y_dest; const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file; std::vector bufVec(stride_file); UChar *buf=&(bufVec[0]); if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || destFormat==CHROMA_400)) { if (destFormat!=CHROMA_400) { // set chrominance data to mid-range: (1<<(fileBitDepth-1)) const Pel value=Pel(1<<(fileBitDepth-1)); for (UInt y = 0; y < full_height_dest; y++, dst+=stride_dest) { for (UInt x = 0; x < full_width_dest; x++) { dst[x] = value; } } } if (fileFormat!=CHROMA_400) { const UInt height_file = height444>>csy_file; fd.seekg(height_file*stride_file, ios::cur); if (fd.eof() || fd.fail() ) { return false; } } } else { const UInt mask_y_file=(1<(buf), stride_file); if (fd.eof() || fd.fail() ) { return false; } } if ((y444&mask_y_dest)==0) { // process current destination line if (csx_file < csx_dest) { // eg file is 444, dest is 422. const UInt sx=csx_dest-csx_file; if (!is16bit) { for (UInt x = 0; x < width_dest; x++) { dst[x] = buf[x<>sx]; } } else { for (UInt x = 0; x < width_dest; x++) { dst[x] = Pel(buf[(x>>sx)*2+0]) | (Pel(buf[(x>>sx)*2+1])<<8); } } } // process right hand side padding const Pel val=dst[width_dest-1]; for (UInt x = width_dest; x < full_width_dest; x++) { dst[x] = val; } dst += stride_dest; } } // process lower padding for (UInt y = height_dest; y < full_height_dest; y++, dst+=stride_dest) { for (UInt x = 0; x < full_width_dest; x++) { dst[x] = (dst - stride_dest)[x]; } } } return true; } /** * Write an image plane (width444*height444 pixels) from src into output stream fd. * * @param fd output file stream * @param src source image * @param is16bit true if input file carries > 8bit data, false otherwise. * @param stride444 distance between vertically adjacent pixels of src. * @param width444 width of active area in src. * @param height444 height of active area in src. * @param compID chroma component * @param srcFormat chroma format of image * @param fileFormat chroma format of file * @param fileBitDepth component bit depth in file * @return true for success, false in case of error */ static Bool writePlane(ostream& fd, Pel* src, Bool is16bit, UInt stride444, UInt width444, UInt height444, const ComponentID compID, const ChromaFormat srcFormat, const ChromaFormat fileFormat, const UInt fileBitDepth) { const UInt csx_file =getComponentScaleX(compID, fileFormat); const UInt csy_file =getComponentScaleY(compID, fileFormat); const UInt csx_src =getComponentScaleX(compID, srcFormat); const UInt csy_src =getComponentScaleY(compID, srcFormat); const UInt stride_src = stride444>>csx_src; const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file; const UInt width_file = width444 >>csx_file; const UInt height_file = height444>>csy_file; std::vector bufVec(stride_file); UChar *buf=&(bufVec[0]); if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400)) { if (fileFormat!=CHROMA_400) { const UInt value=1<<(fileBitDepth-1); for(UInt y=0; y< height_file; y++) { if (!is16bit) { UChar val(value); for (UInt x = 0; x < width_file; x++) { buf[x]=val; } } else { UShort val(value); for (UInt x = 0; x < width_file; x++) { buf[2*x+0]= (val>>0) & 0xff; buf[2*x+1]= (val>>8) & 0xff; } } fd.write(reinterpret_cast(buf), stride_file); if (fd.eof() || fd.fail() ) { return false; } } } } else { const UInt mask_y_file=(1<>sx]); } } else { for (UInt x = 0; x < width_file; x++) { buf[2*x ] = (src[x>>sx]>>0) & 0xff; buf[2*x+1] = (src[x>>sx]>>8) & 0xff; } } } else { // eg file is 422, src is 444. const UInt sx=csx_file-csx_src; if (!is16bit) { for (UInt x = 0; x < width_file; x++) { buf[x] = (UChar)(src[x<>0) & 0xff; buf[2*x+1] = (src[x<>8) & 0xff; } } } fd.write(reinterpret_cast(buf), stride_file); if (fd.eof() || fd.fail() ) { return false; } } if ((y444&mask_y_src)==0) { src += stride_src; } } } return true; } static Bool writeField(ostream& fd, Pel* top, Pel* bottom, Bool is16bit, UInt stride444, UInt width444, UInt height444, const ComponentID compID, const ChromaFormat srcFormat, const ChromaFormat fileFormat, const UInt fileBitDepth, const Bool isTff) { const UInt csx_file =getComponentScaleX(compID, fileFormat); const UInt csy_file =getComponentScaleY(compID, fileFormat); const UInt csx_src =getComponentScaleX(compID, srcFormat); const UInt csy_src =getComponentScaleY(compID, srcFormat); const UInt stride_src = stride444>>csx_src; const UInt stride_file = (width444 * (is16bit ? 2 : 1)) >> csx_file; const UInt width_file = width444 >>csx_file; const UInt height_file = height444>>csy_file; std::vector bufVec(stride_file * 2); UChar *buf=&(bufVec[0]); if (compID!=COMPONENT_Y && (fileFormat==CHROMA_400 || srcFormat==CHROMA_400)) { if (fileFormat!=CHROMA_400) { const UInt value=1<<(fileBitDepth-1); for(UInt y=0; y< height_file; y++) { for (UInt field = 0; field < 2; field++) { UChar *fieldBuffer = buf + (field * stride_file); if (!is16bit) { UChar val(value); for (UInt x = 0; x < width_file; x++) { fieldBuffer[x]=val; } } else { UShort val(value); for (UInt x = 0; x < width_file; x++) { fieldBuffer[2*x+0]= (val>>0) & 0xff; fieldBuffer[2*x+1]= (val>>8) & 0xff; } } } fd.write(reinterpret_cast(buf), (stride_file * 2)); if (fd.eof() || fd.fail() ) { return false; } } } } else { const UInt mask_y_file=(1<>sx]); } } else { for (UInt x = 0; x < width_file; x++) { fieldBuffer[2*x ] = (src[x>>sx]>>0) & 0xff; fieldBuffer[2*x+1] = (src[x>>sx]>>8) & 0xff; } } } else { // eg file is 422, src is 444. const UInt sx=csx_file-csx_src; if (!is16bit) { for (UInt x = 0; x < width_file; x++) { fieldBuffer[x] = (UChar)(src[x<>0) & 0xff; fieldBuffer[2*x+1] = (src[x<>8) & 0xff; } } } } fd.write(reinterpret_cast(buf), (stride_file * 2)); if (fd.eof() || fd.fail() ) { return false; } } if ((y444&mask_y_src)==0) { top += stride_src; bottom += stride_src; } } } return true; } /** * Read one Y'CbCr frame, performing any required input scaling to change * from the bitdepth of the input file to the internal bit-depth. * * If a bit-depth reduction is required, and internalBitdepth >= 8, then * the input file is assumed to be ITU-R BT.601/709 compliant, and the * resulting data is clipped to the appropriate legal range, as if the * file had been provided at the lower-bitdepth compliant to Rec601/709. * * @param pPicYuvUser input picture YUV buffer class pointer * @param pPicYuvTrueOrg * @param ipcsc * @param aiPad source padding size, aiPad[0] = horizontal, aiPad[1] = vertical * @param format chroma format * @return true for success, false in case of error */ Bool TVideoIOYuv::read ( TComPicYuv* pPicYuvUser, TComPicYuv* pPicYuvTrueOrg, const InputColourSpaceConversion ipcsc, Int aiPad[2], ChromaFormat format, const Bool bClipToRec709 ) { // check end-of-file if ( isEof() ) { return false; } TComPicYuv *pPicYuv=pPicYuvTrueOrg; if (format>=NUM_CHROMA_FORMAT) { format=pPicYuv->getChromaFormat(); } Bool is16bit = false; for(UInt ch=0; ch 8) { is16bit=true; } } const UInt stride444 = pPicYuv->getStride(COMPONENT_Y); // compute actual YUV width & height excluding padding size const UInt pad_h444 = aiPad[0]; const UInt pad_v444 = aiPad[1]; const UInt width_full444 = pPicYuv->getWidth(COMPONENT_Y); const UInt height_full444 = pPicYuv->getHeight(COMPONENT_Y); const UInt width444 = width_full444 - pad_h444; const UInt height444 = height_full444 - pad_v444; for(UInt comp=0; comp= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */ const Pel minval = b709Compliance? (( 1 << (desired_bitdepth - 8)) ) : 0; const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1; if (! readPlane(pPicYuv->getAddr(compID), m_cHandle, is16bit, stride444, width444, height444, pad_h444, pad_v444, compID, pPicYuv->getChromaFormat(), format, m_fileBitdepth[chType])) { return false; } if (compID < pPicYuv->getNumberValidComponents() ) { const UInt csx=getComponentScaleX(compID, pPicYuv->getChromaFormat()); const UInt csy=getComponentScaleY(compID, pPicYuv->getChromaFormat()); scalePlane(pPicYuv->getAddr(compID), stride444>>csx, width_full444>>csx, height_full444>>csy, m_bitdepthShift[chType], minval, maxval); } } if(pPicYuvUser) { ColourSpaceConvert(*pPicYuvTrueOrg, *pPicYuvUser, ipcsc, true); } return true; } /** * Write one Y'CbCr frame. No bit-depth conversion is performed, pcPicYuv is * assumed to be at TVideoIO::m_fileBitdepth depth. * * @param pPicYuvUser input picture YUV buffer class pointer * @param ipCSC * @param confLeft conformance window left border * @param confRight conformance window right border * @param confTop conformance window top border * @param confBottom conformance window bottom border * @param format chroma format * @return true for success, false in case of error */ Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUser, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool bClipToRec709 ) { TComPicYuv cPicYuvCSCd; if (ipCSC!=IPCOLOURSPACE_UNCHANGED) { cPicYuvCSCd.createWithoutCUInfo(pPicYuvUser->getWidth(COMPONENT_Y), pPicYuvUser->getHeight(COMPONENT_Y), pPicYuvUser->getChromaFormat() ); ColourSpaceConvert(*pPicYuvUser, cPicYuvCSCd, ipCSC, false); } TComPicYuv *pPicYuv=(ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUser : &cPicYuvCSCd; // compute actual YUV frame size excluding padding size Bool is16bit = false; Bool nonZeroBitDepthShift=false; for(UInt ch=0; ch 8) { is16bit=true; } if (m_bitdepthShift[ch] != 0) { nonZeroBitDepthShift=true; } } TComPicYuv *dstPicYuv = NULL; Bool retval = true; if (format>=NUM_CHROMA_FORMAT) { format=pPicYuv->getChromaFormat(); } if (nonZeroBitDepthShift) { dstPicYuv = new TComPicYuv; dstPicYuv->createWithoutCUInfo( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat() ); for(UInt comp=0; compgetNumberValidComponents(); comp++) { const ComponentID compID=ComponentID(comp); const ChannelType ch=toChannelType(compID); const Bool b709Compliance = bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */ const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0; const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1; copyPlane(*pPicYuv, compID, *dstPicYuv, compID); scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval); } } else { dstPicYuv = pPicYuv; } const Int stride444 = dstPicYuv->getStride(COMPONENT_Y); const UInt width444 = dstPicYuv->getWidth(COMPONENT_Y) - confLeft - confRight; const UInt height444 = dstPicYuv->getHeight(COMPONENT_Y) - confTop - confBottom; if ((width444 == 0) || (height444 == 0)) { printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444); } for(UInt comp=0; retval && compgetNumberValidComponents(); comp++) { const ComponentID compID = ComponentID(comp); const ChannelType ch=toChannelType(compID); const UInt csx = dstPicYuv->getComponentScaleX(compID); const UInt csy = dstPicYuv->getComponentScaleY(compID); const Int planeOffset = (confLeft>>csx) + (confTop>>csy) * dstPicYuv->getStride(compID); if (! writePlane(m_cHandle, dstPicYuv->getAddr(compID) + planeOffset, is16bit, stride444, width444, height444, compID, dstPicYuv->getChromaFormat(), format, m_fileBitdepth[ch])) { retval=false; } } if (nonZeroBitDepthShift) { dstPicYuv->destroy(); delete dstPicYuv; } cPicYuvCSCd.destroy(); return retval; } Bool TVideoIOYuv::write( TComPicYuv* pPicYuvUserTop, TComPicYuv* pPicYuvUserBottom, const InputColourSpaceConversion ipCSC, Int confLeft, Int confRight, Int confTop, Int confBottom, ChromaFormat format, const Bool isTff, const Bool bClipToRec709 ) { TComPicYuv cPicYuvTopCSCd; TComPicYuv cPicYuvBottomCSCd; if (ipCSC!=IPCOLOURSPACE_UNCHANGED) { cPicYuvTopCSCd .createWithoutCUInfo(pPicYuvUserTop ->getWidth(COMPONENT_Y), pPicYuvUserTop ->getHeight(COMPONENT_Y), pPicYuvUserTop ->getChromaFormat() ); cPicYuvBottomCSCd.createWithoutCUInfo(pPicYuvUserBottom->getWidth(COMPONENT_Y), pPicYuvUserBottom->getHeight(COMPONENT_Y), pPicYuvUserBottom->getChromaFormat() ); ColourSpaceConvert(*pPicYuvUserTop, cPicYuvTopCSCd, ipCSC, false); ColourSpaceConvert(*pPicYuvUserBottom, cPicYuvBottomCSCd, ipCSC, false); } TComPicYuv *pPicYuvTop = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserTop : &cPicYuvTopCSCd; TComPicYuv *pPicYuvBottom = (ipCSC==IPCOLOURSPACE_UNCHANGED) ? pPicYuvUserBottom : &cPicYuvBottomCSCd; Bool is16bit = false; Bool nonZeroBitDepthShift=false; for(UInt ch=0; ch 8) { is16bit=true; } if (m_bitdepthShift[ch] != 0) { nonZeroBitDepthShift=true; } } TComPicYuv *dstPicYuvTop = NULL; TComPicYuv *dstPicYuvBottom = NULL; for (UInt field = 0; field < 2; field++) { TComPicYuv *pPicYuv = (field == 0) ? pPicYuvTop : pPicYuvBottom; if (format>=NUM_CHROMA_FORMAT) { format=pPicYuv->getChromaFormat(); } TComPicYuv* &dstPicYuv = (field == 0) ? dstPicYuvTop : dstPicYuvBottom; if (nonZeroBitDepthShift) { dstPicYuv = new TComPicYuv; dstPicYuv->createWithoutCUInfo( pPicYuv->getWidth(COMPONENT_Y), pPicYuv->getHeight(COMPONENT_Y), pPicYuv->getChromaFormat() ); for(UInt comp=0; compgetNumberValidComponents(); comp++) { const ComponentID compID=ComponentID(comp); const ChannelType ch=toChannelType(compID); const Bool b709Compliance=bClipToRec709 && (-m_bitdepthShift[ch] < 0 && m_MSBExtendedBitDepth[ch] >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */ const Pel minval = b709Compliance? (( 1 << (m_MSBExtendedBitDepth[ch] - 8)) ) : 0; const Pel maxval = b709Compliance? ((0xff << (m_MSBExtendedBitDepth[ch] - 8)) -1) : (1 << m_MSBExtendedBitDepth[ch]) - 1; copyPlane(*pPicYuv, compID, *dstPicYuv, compID); scalePlane(dstPicYuv->getAddr(compID), dstPicYuv->getStride(compID), dstPicYuv->getWidth(compID), dstPicYuv->getHeight(compID), -m_bitdepthShift[ch], minval, maxval); } } else { dstPicYuv = pPicYuv; } } Bool retval = true; assert(dstPicYuvTop->getNumberValidComponents() == dstPicYuvBottom->getNumberValidComponents()); assert(dstPicYuvTop->getChromaFormat() == dstPicYuvBottom->getChromaFormat() ); for(UInt comp=0; retval && compgetNumberValidComponents(); comp++) { const ComponentID compID = ComponentID(comp); const ChannelType ch=toChannelType(compID); assert(dstPicYuvTop->getWidth (compID) == dstPicYuvBottom->getWidth (compID)); assert(dstPicYuvTop->getHeight (compID) == dstPicYuvBottom->getHeight (compID)); assert(dstPicYuvTop->getComponentScaleX(compID) == dstPicYuvBottom->getComponentScaleX(compID)); assert(dstPicYuvTop->getComponentScaleY(compID) == dstPicYuvBottom->getComponentScaleY(compID)); assert(dstPicYuvTop->getStride (compID) == dstPicYuvBottom->getStride (compID)); const UInt width444 = dstPicYuvTop->getWidth(COMPONENT_Y) - (confLeft + confRight); const UInt height444 = dstPicYuvTop->getHeight(COMPONENT_Y) - (confTop + confBottom); if ((width444 == 0) || (height444 == 0)) { printf ("\nWarning: writing %d x %d luma sample output picture!", width444, height444); } const UInt csx = dstPicYuvTop->getComponentScaleX(compID); const UInt csy = dstPicYuvTop->getComponentScaleY(compID); const Int planeOffset = (confLeft>>csx) + ( confTop>>csy) * dstPicYuvTop->getStride(compID); //offset is for entire frame - round up for top field and down for bottom field if (! writeField(m_cHandle, (dstPicYuvTop ->getAddr(compID) + planeOffset), (dstPicYuvBottom->getAddr(compID) + planeOffset), is16bit, dstPicYuvTop->getStride(COMPONENT_Y), width444, height444, compID, dstPicYuvTop->getChromaFormat(), format, m_fileBitdepth[ch], isTff)) { retval=false; } } if (nonZeroBitDepthShift) { dstPicYuvTop->destroy(); dstPicYuvBottom->destroy(); delete dstPicYuvTop; delete dstPicYuvBottom; } cPicYuvTopCSCd.destroy(); cPicYuvBottomCSCd.destroy(); return retval; } static Void copyPlane(const TComPicYuv &src, const ComponentID srcPlane, TComPicYuv &dest, const ComponentID destPlane) { const UInt width=src.getWidth(srcPlane); const UInt height=src.getHeight(srcPlane); assert(dest.getWidth(destPlane) == width); assert(dest.getHeight(destPlane) == height); const Pel *pSrc=src.getAddr(srcPlane); Pel *pDest=dest.getAddr(destPlane); const UInt strideSrc=src.getStride(srcPlane); const UInt strideDest=dest.getStride(destPlane); for(UInt y=0; y #include #include #include "TLibCommon/CommonDef.h" #include "TLibCommon/TComPicYuv.h" using namespace std; // ==================================================================================================================== // Class definition // ==================================================================================================================== /// YUV file I/O class class TVideoIOYuv { private: fstream m_cHandle; ///< file handle Int m_fileBitdepth[MAX_NUM_CHANNEL_TYPE]; ///< bitdepth of input/output video file Int m_MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE]; ///< bitdepth after addition of MSBs (with value 0) Int m_bitdepthShift[MAX_NUM_CHANNEL_TYPE]; ///< number of bits to increase or decrease image by before/after write/read public: TVideoIOYuv() {} virtual ~TVideoIOYuv() {} Void open ( const std::string &fileName, Bool bWriteMode, const Int fileBitDepth[MAX_NUM_CHANNEL_TYPE], const Int MSBExtendedBitDepth[MAX_NUM_CHANNEL_TYPE], const Int internalBitDepth[MAX_NUM_CHANNEL_TYPE] ); ///< open or create file Void close (); ///< close file Void skipFrames(Int numFrames, UInt width, UInt height, ChromaFormat format); // if fileFormat #include #include #include #include #include #include #include #include "program_options_lite.h" using namespace std; //! \ingroup TAppCommon //! \{ namespace df { namespace program_options_lite { ErrorReporter default_error_reporter; ostream& ErrorReporter::error(const string& where) { is_errored = 1; cerr << where << " error: "; return cerr; } ostream& ErrorReporter::warn(const string& where) { cerr << where << " warning: "; return cerr; } Options::~Options() { for(Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); it++) { delete *it; } } void Options::addOption(OptionBase *opt) { Names* names = new Names(); names->opt = opt; string& opt_string = opt->opt_string; size_t opt_start = 0; for (size_t opt_end = 0; opt_end != string::npos;) { opt_end = opt_string.find_first_of(',', opt_start); bool force_short = 0; if (opt_string[opt_start] == '-') { opt_start++; force_short = 1; } string opt_name = opt_string.substr(opt_start, opt_end - opt_start); if (force_short || opt_name.size() == 1) { names->opt_short.push_back(opt_name); opt_short_map[opt_name].push_back(names); } else { if (opt_name.size() > 0 && opt_name.back() == '*') { string prefix_name = opt_name.substr(0, opt_name.size() - 1); names->opt_prefix.push_back(prefix_name); opt_prefix_map[prefix_name].push_back(names); } else { names->opt_long.push_back(opt_name); opt_long_map[opt_name].push_back(names); } } opt_start += opt_end + 1; } opt_list.push_back(names); } /* Helper method to initiate adding options to Options */ OptionSpecific Options::addOptions() { return OptionSpecific(*this); } static void setOptions(Options::NamesPtrList& opt_list, const string& value, ErrorReporter& error_reporter) { /* multiple options may be registered for the same name: * allow each to parse value */ for (Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it) { (*it)->opt->parse(value, error_reporter); } } static const char spaces[41] = " "; /* format help text for a single option: * using the formatting: "-x, --long", * if a short/long option isn't specified, it is not printed */ static void doHelpOpt(ostream& out, const Options::Names& entry, unsigned pad_short = 0) { pad_short = min(pad_short, 8u); if (!entry.opt_short.empty()) { unsigned pad = max((int)pad_short - (int)entry.opt_short.front().size(), 0); out << "-" << entry.opt_short.front(); if (!entry.opt_long.empty()) { out << ", "; } out << &(spaces[40 - pad]); } else { out << " "; out << &(spaces[40 - pad_short]); } if (!entry.opt_long.empty()) { out << "--" << entry.opt_long.front(); } else if (!entry.opt_prefix.empty()) { out << "--" << entry.opt_prefix.front() << "*"; } } /* format the help text */ void doHelp(ostream& out, Options& opts, unsigned columns) { const unsigned pad_short = 3; /* first pass: work out the longest option name */ unsigned max_width = 0; for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++) { ostringstream line(ios_base::out); doHelpOpt(line, **it, pad_short); max_width = max(max_width, (unsigned) line.tellp()); } unsigned opt_width = min(max_width+2, 28u + pad_short) + 2; unsigned desc_width = columns - opt_width; /* second pass: write out formatted option and help text. * - align start of help text to start at opt_width * - if the option text is longer than opt_width, place the help * text at opt_width on the next line. */ for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++) { ostringstream line(ios_base::out); line << " "; doHelpOpt(line, **it, pad_short); const string& opt_desc = (*it)->opt->opt_desc; if (opt_desc.empty()) { /* no help text: output option, skip further processing */ cout << line.str() << endl; continue; } size_t currlength = size_t(line.tellp()); if (currlength > opt_width) { /* if option text is too long (and would collide with the * help text, split onto next line */ line << endl; currlength = 0; } /* split up the help text, taking into account new lines, * (add opt_width of padding to each new line) */ for (size_t newline_pos = 0, cur_pos = 0; cur_pos != string::npos; currlength = 0) { /* print any required padding space for vertical alignment */ line << &(spaces[40 - opt_width + currlength]); newline_pos = opt_desc.find_first_of('\n', newline_pos); if (newline_pos != string::npos) { /* newline found, print substring (newline needn't be stripped) */ newline_pos++; line << opt_desc.substr(cur_pos, newline_pos - cur_pos); cur_pos = newline_pos; continue; } if (cur_pos + desc_width > opt_desc.size()) { /* no need to wrap text, remainder is less than avaliable width */ line << opt_desc.substr(cur_pos); break; } /* find a suitable point to split text (avoid spliting in middle of word) */ size_t split_pos = opt_desc.find_last_of(' ', cur_pos + desc_width); if (split_pos != string::npos) { /* eat up multiple space characters */ split_pos = opt_desc.find_last_not_of(' ', split_pos) + 1; } /* bad split if no suitable space to split at. fall back to width */ bool bad_split = split_pos == string::npos || split_pos <= cur_pos; if (bad_split) { split_pos = cur_pos + desc_width; } line << opt_desc.substr(cur_pos, split_pos - cur_pos); /* eat up any space for the start of the next line */ if (!bad_split) { split_pos = opt_desc.find_first_not_of(' ', split_pos); } cur_pos = newline_pos = split_pos; if (cur_pos >= opt_desc.size()) { break; } line << endl; } cout << line.str() << endl; } } struct OptionWriter { OptionWriter(Options& rOpts, ErrorReporter& err) : opts(rOpts), error_reporter(err) {} virtual ~OptionWriter() {} virtual const string where() = 0; bool storePair(bool allow_long, bool allow_short, const string& name, const string& value); bool storePair(const string& name, const string& value) { return storePair(true, true, name, value); } Options& opts; ErrorReporter& error_reporter; }; bool OptionWriter::storePair(bool allow_long, bool allow_short, const string& name, const string& value) { bool found = false; std::string val = value; Options::NamesMap::iterator opt_it; if (allow_long) { opt_it = opts.opt_long_map.find(name); if (opt_it != opts.opt_long_map.end()) { found = true; } } /* check for the short list */ if (allow_short && !(found && allow_long)) { opt_it = opts.opt_short_map.find(name); if (opt_it != opts.opt_short_map.end()) { found = true; } } bool allow_prefix = allow_long; if (allow_prefix && !found) { for (opt_it = opts.opt_prefix_map.begin(); opt_it != opts.opt_prefix_map.end(); opt_it++) { std::string name_prefix = name.substr(0, opt_it->first.size()); if (name_prefix == opt_it->first) { // prepend value matching * val = name.substr(name_prefix.size()) + std::string(" ") + val; found = true; break; } } } if (!found) { error_reporter.error(where()) << "Unknown option `" << name << "' (value:`" << value << "')\n"; return false; } setOptions((*opt_it).second, val, error_reporter); return true; } struct ArgvParser : public OptionWriter { ArgvParser(Options& rOpts, ErrorReporter& rError_reporter) : OptionWriter(rOpts, rError_reporter) {} const string where() { return "command line"; } unsigned parseGNU(unsigned argc, const char* argv[]); unsigned parseSHORT(unsigned argc, const char* argv[]); }; /** * returns number of extra arguments consumed */ unsigned ArgvParser::parseGNU(unsigned argc, const char* argv[]) { /* gnu style long options can take the forms: * --option=arg * --option arg */ string arg(argv[0]); size_t arg_opt_start = arg.find_first_not_of('-'); size_t arg_opt_sep = arg.find_first_of('='); string option = arg.substr(arg_opt_start, arg_opt_sep - arg_opt_start); unsigned extra_argc_consumed = 0; if (arg_opt_sep == string::npos) { /* no argument found => argument in argv[1] (maybe) */ /* xxx, need to handle case where option isn't required */ #if 0 /* commented out, to return to true GNU style processing * where longopts have to include an =, otherwise they are * booleans */ if (argc == 1) { return 0; /* run out of argv for argument */ } extra_argc_consumed = 1; #endif if(!storePair(true, false, option, "1")) { return 0; } } else { /* argument occurs after option_sep */ string val = arg.substr(arg_opt_sep + 1); storePair(true, false, option, val); } return extra_argc_consumed; } unsigned ArgvParser::parseSHORT(unsigned argc, const char* argv[]) { /* short options can take the forms: * --option arg * -option arg */ string arg(argv[0]); size_t arg_opt_start = arg.find_first_not_of('-'); string option = arg.substr(arg_opt_start); /* lookup option */ /* argument in argv[1] */ /* xxx, need to handle case where option isn't required */ if (argc == 1) { error_reporter.error(where()) << "Not processing option `" << option << "' without argument\n"; return 0; /* run out of argv for argument */ } storePair(false, true, option, string(argv[1])); return 1; } list scanArgv(Options& opts, unsigned argc, const char* argv[], ErrorReporter& error_reporter) { ArgvParser avp(opts, error_reporter); /* a list for anything that didn't get handled as an option */ list non_option_arguments; for(unsigned i = 1; i < argc; i++) { if (argv[i][0] != '-') { non_option_arguments.push_back(argv[i]); continue; } if (argv[i][1] == 0) { /* a lone single dash is an argument (usually signifying stdin) */ non_option_arguments.push_back(argv[i]); continue; } if (argv[i][1] != '-') { /* handle short (single dash) options */ i += avp.parseSHORT(argc - i, &argv[i]); continue; } if (argv[i][2] == 0) { /* a lone double dash ends option processing */ while (++i < argc) { non_option_arguments.push_back(argv[i]); } break; } /* handle long (double dash) options */ i += avp.parseGNU(argc - i, &argv[i]); } return non_option_arguments; } struct CfgStreamParser : public OptionWriter { CfgStreamParser(const string& rName, Options& rOpts, ErrorReporter& rError_reporter) : OptionWriter(rOpts, rError_reporter) , name(rName) , linenum(0) {} const string name; int linenum; const string where() { ostringstream os; os << name << ":" << linenum; return os.str(); } void scanLine(string& line); void scanStream(istream& in); }; void CfgStreamParser::scanLine(string& line) { /* strip any leading whitespace */ size_t start = line.find_first_not_of(" \t\n\r"); if (start == string::npos) { /* blank line */ return; } if (line[start] == '#') { /* comment line */ return; } /* look for first whitespace or ':' after the option end */ size_t option_end = line.find_first_of(": \t\n\r",start); string option = line.substr(start, option_end - start); /* look for ':', eat up any whitespace first */ start = line.find_first_not_of(" \t\n\r", option_end); if (start == string::npos) { /* error: badly formatted line */ error_reporter.warn(where()) << "line formatting error\n"; return; } if (line[start] != ':') { /* error: badly formatted line */ error_reporter.warn(where()) << "line formatting error\n"; return; } /* look for start of value string -- eat up any leading whitespace */ start = line.find_first_not_of(" \t\n\r", ++start); if (start == string::npos) { /* error: badly formatted line */ error_reporter.warn(where()) << "line formatting error\n"; return; } /* extract the value part, which may contain embedded spaces * by searching for a word at a time, until we hit a comment or end of line */ size_t value_end = start; do { if (line[value_end] == '#') { /* rest of line is a comment */ value_end--; break; } value_end = line.find_first_of(" \t\n\r", value_end); /* consume any white space, incase there is another word. * any trailing whitespace will be removed shortly */ value_end = line.find_first_not_of(" \t\n\r", value_end); } while (value_end != string::npos); /* strip any trailing space from value*/ value_end = line.find_last_not_of(" \t\n\r", value_end); string value; if (value_end >= start) { value = line.substr(start, value_end +1 - start); } else { /* error: no value */ error_reporter.warn(where()) << "no value found\n"; return; } /* store the value in option */ storePair(true, false, option, value); } void CfgStreamParser::scanStream(istream& in) { do { linenum++; string line; getline(in, line); scanLine(line); } while(!!in); } /* for all options in opts, set their storage to their specified * default value */ void setDefaults(Options& opts) { for(Options::NamesPtrList::iterator it = opts.opt_list.begin(); it != opts.opt_list.end(); it++) { (*it)->opt->setDefault(); } } void parseConfigFile(Options& opts, const string& filename, ErrorReporter& error_reporter) { ifstream cfgstream(filename.c_str(), ifstream::in); if (!cfgstream) { error_reporter.error(filename) << "Failed to open config file\n"; return; } CfgStreamParser csp(filename, opts, error_reporter); csp.scanStream(cfgstream); } } } //! \} HM-HM-18.0/source/Lib/Utilities/program_options_lite.h000066400000000000000000000215421442026013100226360ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "TLibCommon/CommonDef.h" #ifndef __PROGRAM_OPTIONS_LITE__ #define __PROGRAM_OPTIONS_LITE__ //! \ingroup TAppCommon //! \{ #if JVET_X0048_X0103_FILM_GRAIN template struct SMultiValueInput { const T minValIncl; const T maxValIncl; const std::size_t minNumValuesIncl; const std::size_t maxNumValuesIncl; // Use 0 for unlimited std::vector values; SMultiValueInput() : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values() { } SMultiValueInput(std::vector &defaults) : minValIncl(0), maxValIncl(0), minNumValuesIncl(0), maxNumValuesIncl(0), values(defaults) { } SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues = 0, std::size_t maxNumberValues = 0) : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values() { } SMultiValueInput(const T &minValue, const T &maxValue, std::size_t minNumberValues, std::size_t maxNumberValues, const T* defValues, const UInt numDefValues) : minValIncl(minValue), maxValIncl(maxValue), minNumValuesIncl(minNumberValues), maxNumValuesIncl(maxNumberValues), values(defValues, defValues + numDefValues) { } SMultiValueInput &operator=(const std::vector &userValues) { values = userValues; return *this; } SMultiValueInput &operator=(const SMultiValueInput &userValues) { values = userValues.values; return *this; } T readValue(const TChar *&pStr, Bool &bSuccess); std::istream& readValues(std::istream &in); }; #endif namespace df { namespace program_options_lite { struct Options; struct ParseFailure : public std::exception { ParseFailure(std::string arg0, std::string val0) throw() : arg(arg0), val(val0) {} ~ParseFailure() throw() {}; std::string arg; std::string val; const char* what() const throw() { return "Option Parse Failure"; } }; struct ErrorReporter { ErrorReporter() : is_errored(0) {} virtual ~ErrorReporter() {} virtual std::ostream& error(const std::string& where); virtual std::ostream& warn(const std::string& where); bool is_errored; }; extern ErrorReporter default_error_reporter; void doHelp(std::ostream& out, Options& opts, unsigned columns = 80); std::list scanArgv(Options& opts, unsigned argc, const char* argv[], ErrorReporter& error_reporter = default_error_reporter); void setDefaults(Options& opts); void parseConfigFile(Options& opts, const std::string& filename, ErrorReporter& error_reporter = default_error_reporter); /** OptionBase: Virtual base class for storing information relating to a * specific option This base class describes common elements. Type specific * information should be stored in a derived class. */ struct OptionBase { OptionBase(const std::string& name, const std::string& desc) : opt_string(name), opt_desc(desc) {}; virtual ~OptionBase() {} /* parse argument arg, to obtain a value for the option */ virtual void parse(const std::string& arg, ErrorReporter&) = 0; /* set the argument to the default value */ virtual void setDefault() = 0; std::string opt_string; std::string opt_desc; }; /** Type specific option storage */ template struct Option : public OptionBase { Option(const std::string& name, T& storage, T default_val, const std::string& desc) : OptionBase(name, desc), opt_storage(storage), opt_default_val(default_val) {} void parse(const std::string& arg, ErrorReporter&); void setDefault() { opt_storage = opt_default_val; } T& opt_storage; T opt_default_val; }; /* Generic parsing */ template inline void Option::parse(const std::string& arg, ErrorReporter&) { std::istringstream arg_ss (arg,std::istringstream::in); arg_ss.exceptions(std::ios::failbit); try { arg_ss >> opt_storage; } catch (...) { throw ParseFailure(opt_string, arg); } } /* string parsing is specialized -- copy the whole string, not just the * first word */ template<> inline void Option::parse(const std::string& arg, ErrorReporter&) { opt_storage = arg; } /** Option class for argument handling using a user provided function */ struct OptionFunc : public OptionBase { typedef void (Func)(Options&, const std::string&, ErrorReporter&); OptionFunc(const std::string& name, Options& parent_, Func *func_, const std::string& desc) : OptionBase(name, desc), parent(parent_), func(func_) {} void parse(const std::string& arg, ErrorReporter& error_reporter) { func(parent, arg, error_reporter); } void setDefault() { return; } private: Options& parent; Func* func; }; class OptionSpecific; struct Options { ~Options(); OptionSpecific addOptions(); struct Names { Names() : opt(0) {}; ~Names() { if (opt) { delete opt; } } std::list opt_long; std::list opt_prefix; std::list opt_short; OptionBase* opt; }; void addOption(OptionBase *opt); typedef std::list NamesPtrList; NamesPtrList opt_list; typedef std::map NamesMap; NamesMap opt_long_map; NamesMap opt_short_map; NamesMap opt_prefix_map; }; /* Class with templated overloaded operator(), for use by Options::addOptions() */ class OptionSpecific { public: OptionSpecific(Options& parent_) : parent(parent_) {} /** * Add option described by name to the parent Options list, * with storage for the option's value * with default_val as the default value * with desc as an optional help description */ template OptionSpecific& operator()(const std::string& name, T& storage, T default_val, const std::string& desc = "") { parent.addOption(new Option(name, storage, default_val, desc)); return *this; } /** * Add option described by name to the parent Options list, * with desc as an optional help description * instead of storing the value somewhere, a function of type * OptionFunc::Func is called. It is upto this function to correctly * handle evaluating the option's value. */ OptionSpecific& operator()(const std::string& name, OptionFunc::Func *func, const std::string& desc = "") { parent.addOption(new OptionFunc(name, parent, func, desc)); return *this; } private: Options& parent; }; } /* namespace: program_options_lite */ } /* namespace: df */ //! \} #endif HM-HM-18.0/source/Lib/libmd5/000077500000000000000000000000001442026013100154235ustar00rootroot00000000000000HM-HM-18.0/source/Lib/libmd5/MD5.h000066400000000000000000000047021442026013100161640ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "libmd5.h" #include //! \ingroup libMD5 //! \{ static const UInt MD5_DIGEST_STRING_LENGTH=16; class MD5 { public: /** * initialize digest state */ MD5() { MD5Init(&m_state); } /** * compute digest over buf of length len. * multiple calls may extend the digest over more data. */ void update(unsigned char *buf, unsigned len) { MD5Update(&m_state, buf, len); } /** * flush any outstanding MD5 data, write the digest into digest. */ void finalize(unsigned char digest[MD5_DIGEST_STRING_LENGTH]) { MD5Final(digest, &m_state); } private: context_md5_t m_state; }; //! \} HM-HM-18.0/source/Lib/libmd5/libmd5.cpp000066400000000000000000000177371442026013100173220ustar00rootroot00000000000000/* * This code implements the MD5 message-digest algorithm. The algorithm was * written by Ron Rivest. This code was written by Colin Plumb in 1993, our * understanding is that no copyright is claimed and that this code is in the * public domain. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is functionally equivalent, * * To compute the message digest of a chunk of bytes, declare an MD5Context * structure, pass it to MD5Init, call MD5Update as needed on buffers full of * bytes, and then call MD5Final, which will fill a supplied 16-byte array with * the digest. */ #include #include #include "libmd5.h" //! \ingroup libMD5 //! \{ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); #ifndef __BIG_ENDIAN__ # define byteReverse(buf, len) /* Nothing */ #else void byteReverse(uint32_t *buf, unsigned len); /* * Note: this code is harmless on little-endian machines. */ void byteReverse(uint32_t *buf, unsigned len) { uint32_t t; do { char* bytes = (char *) buf; t = ((unsigned) bytes[3] << 8 | bytes[2]) << 16 | ((unsigned) bytes[1] << 8 | bytes[0]); *buf = t; buf++; } while (--len); } #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(context_md5_t *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(context_md5_t *ctx, unsigned char *buf, unsigned len) { uint32_t t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = ctx->in.b8 + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->in.b32, 16); MD5Transform(ctx->buf, ctx->in.b32); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in.b8, buf, 64); byteReverse(ctx->in.b32, 16); MD5Transform(ctx->buf, ctx->in.b32); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in.b8, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], context_md5_t *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in.b8 + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in.b32, 16); MD5Transform(ctx->buf, ctx->in.b32); /* Now fill the next block with 56 bytes */ memset(ctx->in.b8, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in.b32, 14); /* Append length in bits and transform */ ctx->in.b32[14] = ctx->bits[0]; ctx->in.b32[15] = ctx->bits[1]; MD5Transform(ctx->buf, ctx->in.b32); byteReverse((uint32_t *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(* ctx)); /* In case it's sensitive */ /* The original version of this code omitted the asterisk. In effect, only the first part of ctx was wiped with zeros, not the whole thing. Bug found by Derek Jones. Original line: */ // memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) { register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } HM-HM-18.0/source/Lib/libmd5/libmd5.h000066400000000000000000000043621442026013100167550ustar00rootroot00000000000000/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include //! \ingroup libMD5 //! \{ typedef struct _context_md5_t { uint32_t buf[4]; uint32_t bits[2]; union { unsigned char b8[64]; uint32_t b32[16]; } in; } context_md5_t; #ifdef __cplusplus extern "C" { #endif void MD5Init(context_md5_t *ctx); void MD5Update(context_md5_t *ctx, unsigned char *buf, unsigned len); void MD5Final(unsigned char digest[16], context_md5_t *ctx); #ifdef __cplusplus } #endif //! \}